Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 5 Nov 2026. What's built · Install 0.3.0
jadpo
ReferenceErrors

ErrorsReads and writes · rule

data.update_by_id_value

On this page

An update by id sets a value that the database can't work out on its own, such as one read earlier in the action.

Area 6, Reads and writes; not declinable; the next step is usually the agent's.

Why Jadpo refuses it

An update by id is one statement, worked out by the database at the moment it writes. Its values may use only the action's parameters, constants, clock.now and the record's stored fields, and a stored field only with + and -.

Here hits comes from counter, a copy loaded earlier. Another request could add a hit between the read and the write, and this update would then overwrite it, so a hit would be lost.

What it looks like

main.jadpo:

example
type Count = Int {    min: 0}entity Counter {    id: Uuid    hits: Count}action hit(counter_id: Counter.id) fails CounterNotFound -> Counter {    var counter: Counter = attempt Counter.get(counter_id)    return attempt Counter.update(counter_id) {        set: {            hits: Count(counter.hits + 1)        }    }}
jadpo checkcheck failed: 1 error, 1 file

error Counter.update by id sets a value from counter, a variable

--> main.jadpo:14:25

   |14 |             hits: Count(counter.hits + 1)   |                         ^^^^^^^ a variable
reason
An update by id is worked out by the database in one step, so its values use only the action's parameters, constants, clock.now and Counter's stored fields; a value read earlier could have changed by the time it writes.
next
Load the record and update it, Counter.update(counter) { set: { ... } }, or pass the value in as a parameter (agent)
rule
data.update_by_id_value
help
https://jadpo.dev/docs/errors/data.update_by_id_value

(agent) at the end of the next: line means your coding agent can make the fix itself.

How to fix it

If the new value depends only on the stored one, name the stored field, Counter.hits, and drop the read:

example
action hit(counter_id: Counter.id) fails CounterNotFound -> Counter {    return attempt Counter.update(counter_id) {        set: {            hits: Count(Counter.hits + 1)        }    }}

The database adds 1 to the stored count in one statement, so no hit is lost. The action loads no record, so it runs at read committed, and a second request counting at the same time waits for the first and then adds to its count.

If the action needs the loaded record anyway, update that record rather than its id:

example
    var counter: Counter = attempt Counter.get(counter_id)    return Counter.update(counter) {        set: {            hits: Count(counter.hits + 1)        }    }

The action now runs at repeatable read, because it loads the counter. A request that changes the same counter at the same time makes it run again, so the hit still isn't lost.

Markdown for agents: /docs/errors/data.update_by_id_value.md.Built from Jadpo main at aee2e8f.