Error codes · Declarations and their clauses

PW0338

sent_without_idempotency

The program must hold to this: a command a page's handler calls declares idempotent_by.

A program the compiler refuses with it

Refused: PW0338
module twice

import context.{ current_session }
import capability.{ Session, SessionId }

type Post = Post { id: String, text: String }

type PostError =
    | Unavailable

fn publish(s: Session<SessionId>, text: String) -> Result<Post, PostError> !{ database.write<Post> }
    host "blog:data/posts#publish"

command post(text: String) -> Result<Post, PostError> {
    publish(current_session(), text)
}

page Write() {
    route "/write"

    signal sent: Int = 0

    view {
        <title>Write</title>
        <button type="button" on:press={() => match post("Hello") {
            Ok(_) => sent = sent + 1,
            Err(_) => (),
        }}>Post</button>
    }
}
pw check
error: [PW0338] `post` is called by a page's handler, and declares no `idempotent_by`
  --> twice.pw:14:1
   |
14 | / command post(text: String) -> Result<Post, PostError> {
15 | |     publish(current_session(), text)
16 | | }
   | |_^ `post` is called by a page's handler, and declares no `idempotent_by`
...
25 |           <button type="button" on:press={() => match post("Hello") {
   |                                                       ------------- a press sends it from here
   |
   = note: A browser's request can reach the server twice: a retrying proxy, a flaky network or a client's own retry sends it again after the first arrived (RFC 9110 lets a client retry only a request it knows to be idempotent). Each press carries an interaction, and `idempotent_by InteractionId` runs the command once for it (ADR-0121).
   = help: declare `idempotent_by InteractionId`

From A command a page can send twice, in Errors and diagnostics. A test holds the guide's examples to the compiler.

The decisions behind it

0154

Reading the diagnostic

pw check prints the code in brackets, [PW0338], with the sentence above and the place in your program. Errors and diagnostics explains how to read one, and every code is listed with its rule.