Skip to content

feat: say why a fault happened, and stop faking ordinal 0 everywhere - #21

Merged
Kinflou merged 1 commit into
mainfrom
feat/fault-notes
Oct 17, 2026
Merged

Kinflou merged 1 commit into
mainfrom
feat/fault-notes

Conversation

@Kinflou

@Kinflou Kinflou commented Oct 17, 2026

Copy link
Copy Markdown
Member

#20 left six sites still answering a failure with ordinal: 0 and an
{"error": "…"} body, because each carried a message the user needs and a
fault is opaque on the wire, so there was nowhere else to put the text. This
adds that place.

Where the reason goes

SimOutcome::Fault now carries an optional note, and it never reaches the
wire
. reply_now pins it to the response frame it just emitted, and
describe_frame hands it to the inspector as FrameDetail::note. The
simulator is both ends of the connection, so it can show what a real provider
would only have logged.

The note is a separate field, Frame::note, rather than reusing
Frame::fault. That field already means something else: what the wire's fault
injection did to a frame (dropped, corrupted, +40 ms).

Sites converted

  • Forward with no connection picked
  • begin_forward's refusals: no such connection, a refused connection, a
    forwarding cycle, a target without that function
  • a relayed upstream fault, timeout or undecodable reply, now naming the
    connection that failed. A cycle reads forwarding cycle at the innermost hop
    and forward: <conn> faulted at each hop outward, which the test pins.
  • a script that throws, errors at runtime, or does not compile
  • the disabled-script stub

Before this, every one of these reached the caller as a schema error. Its
client decodes ordinal 0 as whichever declared error happens to hold it, so the
caller got a wrong answer rather than a failure.

A one-way bug these sites shared

A failing script on a one-way function emitted a response frame that no
caller was waiting for. fault_or_none now mirrors the existing ok_or_none:
a one-way call has no response frame to carry a fault, so it sends nothing.
That matches the runtime's rule that a one-way handler cannot fail.

Behaviour change

A script's throw used to raise ordinal: 0. It now faults, with the thrown
value as the note. It could never name a declared error anyway.

Verification

137 tests pass with the default script feature, 128 without. Clippy is clean
on both, and the crate builds for wasm32-unknown-unknown.

simulator#20 left six sites that still answered a failure with
`ordinal: 0` and an `{"error": "..."}` body, because each carried a
message the user needs and a fault is opaque on the wire — there was
nowhere else to put the text. This adds that somewhere.

`SimOutcome::Fault` now carries an optional `note`. It never reaches
the wire. `reply_now` pins it to the response frame it just emitted
(`Frame::note`, distinct from the existing `Frame::fault`, which is what
the wire's fault injection did to a frame), and `describe_frame` hands
it to the inspector as `FrameDetail::note`. The simulator is both ends,
so it can show what a real provider would only have logged.

Every site now faults with a note:

- `Forward` with no connection picked
- `begin_forward`'s refusals: no such connection, a refused connection,
  a forwarding cycle, a target without that function
- a relayed upstream fault, timeout or undecodable reply, naming the
  connection that failed — so a cycle reads "forwarding cycle" at the
  innermost hop and "forward: <conn> faulted" at each hop outward
- a script that throws, errors at runtime, or does not compile
- the disabled-script stub

Before, every one of these reached the caller as a *schema* error: its
client decodes ordinal 0 as whichever declared error happens to hold
it, a wrong answer rather than a failure.

Also fixes a one-way bug these sites shared: a failing script on a
one-way function emitted a response frame no caller was waiting for.
`fault_or_none` mirrors `ok_or_none` — a one-way call has no response
to carry a fault, so it sends nothing.

Behaviour change worth knowing: a script's `throw` used to raise
`ordinal: 0`; it now faults, with the thrown value as the note. It
could never name a declared error anyway.

137 tests pass with the `script` feature, 128 without; clippy clean on
both, builds for wasm32.
@Kinflou
Kinflou merged commit affe200 into main Oct 17, 2026
1 check passed
@Kinflou
Kinflou deleted the feat/fault-notes branch October 18, 2026 02:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant