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

ErrorsEntities, stores and migrations · rule

data.lifecycle_condition

On this page

A lifecycle's visible: or when: condition isn't a plain test of the record's own fields against fixed values.

Area 5, Entities, stores and migrations; not declinable; the next step is usually the agent's.

Why Jadpo refuses it

A lifecycle's conditions are about the record they are written in. They compare its fields with fixed values: a literal, an enum value, none or clock.now. Because of that, Jadpo can add visible: to every statement that reads the entity, and to an index, without knowing who is asking.

A condition that mentions another record, or the person making the request, can't become part of every statement in that way. Who may see a record is a different question, and the entity's policy: answers it.

What it looks like

main.jadpo:

example
entity Todo {    id: Uuid    owner_id: Uuid    deleted_at: Instant?    lifecycle: {        visible: deleted_at == none and owner_id == current_user.id    }}
jadpo checkcheck failed: 1 error, 1 file

error current_user.id isn't something a lifecycle condition can compare with

--> main.jadpo:7:53

  |7 |         visible: deleted_at == none and owner_id == current_user.id  |                                                     ^^^^^^^^^^^^^^^ from outside the record
reason
A lifecycle condition compares the record's own fields with fixed values: a literal, an enum value or clock.now. It never mentions other records or who is asking, which is policy (area 9), so it can join every statement's WHERE and an index.
next
Compare with a literal, an enum value or clock.now (agent)
rule
data.lifecycle_condition
help
https://jadpo.dev/docs/errors/data.lifecycle_condition

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

A condition that names a field with its entity in front, as a query writes it, is refused too. Inside the lifecycle the record is already known, so its fields are named bare.

main.jadpo:

example
entity Todo {    id: Uuid    deleted_at: Instant?    lifecycle: {        visible: Todo.deleted_at == none    }}
jadpo checkcheck failed: 1 error, 1 file

error Todo.deleted_at names its own entity

--> main.jadpo:6:18

  |6 |         visible: Todo.deleted_at == none  |                  ^^^^^^^^^^^^^^^ written as a query writes it
reason
A lifecycle's conditions are about the record they are written in, so they name its fields bare: deleted_at, not Todo.deleted_at.
next
Write deleted_at (agent)
rule
data.lifecycle_condition
help
https://jadpo.dev/docs/errors/data.lifecycle_condition

How to fix it

If the condition says who may see the record, keep only the test of the record's own fields in visible:, and say who may read it in the entity's policy:. Here owner_id becomes a reference to the User who owns the todo, so read: [owner_id] lets that user read it:

example
    owner_id: User.id {        on_delete: OnDelete.cascade    }    deleted_at: Instant?    lifecycle: {        visible: deleted_at == none    }    policy: {        read: [owner_id]    }

Deleted todos still drop out of every read. Each signed-in user now reads only the todos they own, and policy refuses the rest.

If a field is written with its entity's name, write it bare:

example
        visible: deleted_at == none

The condition means the same as before, and normal reads leave out todos whose deleted_at is set.

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