route.run_kind
A GET route runs an action that isn't read-only, or a route of another method runs a query.
Area 7, HTTP; not declinable; the next step is usually the agent's.
Why Jadpo refuses it
HTTP promises that a GET only reads, so a browser, a cache or a client
library may send one again without asking. Jadpo keeps that promise by what
a route runs. A query can only read, so a GET can run one. An action can
write, so a GET runs one only when the compiler can prove it writes
nothing, emits nothing and makes no changing call, itself and through every
action it calls. POST, PUT, PATCH and DELETE run an action, which owns
the writes and the transaction, and never a query.
A GET running an action that changes something could change it again each
time it is repeated, and nothing can show whether you meant the route to read
or to write. The message names what the action does and where, following the
calls, so you can see which it is.
What it looks like
Here the action adds a note, so it can't answer a GET:
main.jadpo:
type Memo = Text { max_length: 200}type AddMemo = Input { text: Memo}type MemoView = Output { text: Memo}entity Note { id: Uuid text: Memo policy: { create: [Access.public] read: [Access.public] }}action add_memo(input: AddMemo) -> MemoView { var note: Note = Note.create { set: { text: input.text } } return MemoView { text: note.text }}routes Memos { prefix: /memos GET / { authentication: RouteAuthentication.none input: AddMemo output: MemoView run: add_memo(input) }}
error GET /memos runs action add_memo, which writes with Note.create
--> main.jadpo:41:14
|24 | var note: Note = Note.create { | ----------- here41 | run: add_memo(input) | ^^^^^^^^ not read-only
- reason
- A
GETis safe to repeat, so it runs a named query, or an action the graph proves writes nothing, emits nothing and makes no changing call;add_memowrites withNote.create. - next
- Answer
/memoswith another method, or leaveNote.createout of whatadd_memodoes (agent) - rule
- route.
run_ kind - help
- https://jadpo.
dev/docs/errors/route. run_ kind
(agent) at the end of the next: line means your coding agent can make
the fix itself.
How to fix it
The question is whether the route changes anything.
If the route adds or changes something, answer it with another
method, here POST, which reads its input from the JSON body:
POST / { authentication: RouteAuthentication.none input: AddMemo output: MemoView run: add_memo(input) }
POST /memos runs add_memo, and a client sends the memo as JSON.
If the route only reads, run a query that reads what it shows, or
leave what changes something out of the action. Here the memos are stored as
Note records, and the route lists them:
query recent_notes() -> List<MemoView> { from: Note order: [Note.text asc] limit: 50}
GET / { output: List<MemoView> run: recent_notes() }
GET /memos answers with up to 50 notes and never writes, so repeating
it is safe. A signed-in caller sees the notes Note's read: lets them
read.
An action that works something out can stay on the GET, once it stops
doing what changes something. An action like this one, which reads and
calculates, has nothing to refuse:
action check_memo(input: MemoInput) fails TooShort -> MemoView { if (text.length(input.text) < 3) { reject TooShort {} } return MemoView { text: input.text }}
GET /memos now answers with the memo, or 422 too_short, and repeating it
changes nothing.
Related
Markdown for agents: /docs/errors/route.run_kind.md.Built from Jadpo main at aee2e8f.