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.lifecycle_hard_delete

On this page

Code would remove a record that has a lifecycle for good, which only the lifecycle's own purge may do.

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

Why Jadpo refuses it

A lifecycle keeps a record through its stages, and only its own purge removes a record for good, once it has been hidden long enough. Code never removes such a record. Article.delete runs the lifecycle's delete transition, which changes the record and keeps it, and Article's lifecycle has none.

Jadpo won't add the transition for you, because it decides what deleting an article means: which field records it, and whether the article is ever removed for good.

What it looks like

main.jadpo:

example
type ArticleTitle = Text {    max_length: 120}entity Article {    id: Uuid    title: ArticleTitle    published_at: Instant?    lifecycle: {        visible: published_at != none and published_at <= clock.now    }}action remove_article(article: Article) -> Unit {    Article.delete(article)}
jadpo checkcheck failed: 1 error, 1 file

error Article.delete would remove a record Article's lifecycle keeps

--> main.jadpo:16:5

   |16 |     Article.delete(article)   |     ^^^^^^^^^^^^^^ a lifecycle keeps it
reason
Code never removes a record that has a lifecycle: delete runs its delete transition, and Article's lifecycle has none. Only purge, the compiler's own, removes such records, once they have been hidden long enough.
next
Add a delete transition to Article's lifecycle, saying what deleting one changes (human)
rule
data.lifecycle_hard_delete
help
https://jadpo.dev/docs/errors/data.lifecycle_hard_delete

(human) at the end of the next: line tells your coding agent to stop and ask you which fix you want, because the choice is yours to make: it decides what deleting an article does, and whether it is ever removed for good.

Deleting a record of another entity is refused in the same way when the delete would cascade to a record with a lifecycle. Here deleting an author would delete their articles:

main.jadpo:

example
type ArticleTitle = Text {    max_length: 120}entity Author {    id: Uuid}entity Article {    id: Uuid    author_id: Author.id {        on_delete: OnDelete.cascade    }    title: ArticleTitle    published_at: Instant?    lifecycle: {        visible: published_at != none and published_at <= clock.now    }}action remove_author(author: Author) -> Unit {    Author.delete(author)}
jadpo checkcheck failed: 1 error, 1 file

error Author.delete would remove Article records their lifecycle keeps

--> main.jadpo:23:5

   |23 |     Author.delete(author)   |     ^^^^^^^^^^^^^ a lifecycle keeps it
reason
Removing a Author removes the Article records whose author_id points at it (on_delete: OnDelete.cascade), and Article has a lifecycle; code never removes a record that has one.
next
Give Author a lifecycle with a delete transition, or change Article.author_id's on_delete: (human)
rule
data.lifecycle_hard_delete
help
https://jadpo.dev/docs/errors/data.lifecycle_hard_delete

How to fix it

If a deleted article should be hidden and kept, give the lifecycle a delete transition that records when it happened, and leave out records it has set from visible::

example
    removed_at: Instant?    lifecycle: {        visible: removed_at == none and published_at != none and published_at <= clock.now        transitions: {            delete: {                set: {                    removed_at: clock.now                }            }        }    }

Article.delete now sets removed_at. The article drops out of every read but stays in the database, where it can be looked into or restored.

If a deleted article should later be removed for good, add a purge: to the same lifecycle as well:

example
        purge: {            after: 30d            since: removed_at        }

Deleting hides the article at once. Thirty days after removed_at, the built-in hourly purge removes it for good, along with any other hidden article whose removed_at is older.

If deleting an author should be refused while they have articles, make the reference restricted, and map the refusal in the delete's conflict::

example
    author_id: Author.id {        on_delete: OnDelete.restricted    }
example
type AuthorHasArticles = Failure {    kind: FailureKind.conflict}action remove_author(author: Author) fails AuthorHasArticles -> Unit {    attempt Author.delete(author) {        conflict: {            Article.author_id: AuthorHasArticles        }    }}

Deleting an author fails with AuthorHasArticles while any article refers to them, and their articles are never removed by it. An author can instead be given a lifecycle of their own with a delete transition, so deleting one hides them and keeps their articles.

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