Skip to content

Error taxonomy names the documented failure modes: timed-out, not-supported, in-use - #59

Merged
lann merged 3 commits into
mainfrom
error-taxonomy
Aug 12, 2026
Merged

Error taxonomy names the documented failure modes: timed-out, not-supported, in-use#59
lann merged 3 commits into
mainfrom
error-taxonomy

Conversation

@lannbot

@lannbot lannbot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Issue #13 findings C14 and D16 — the first of the two C/D-tail PRs discussed (the contract-truthfulness sweep follows separately).

Three failure modes the docs already described were riding cases that misnamed them:

timed-out(string)

A dial the peer never answers, and a relay open that never completes, get their own case. Consumers legitimately dispatch on the difference (retry a timeout; don't retry a refusal), and noq distinguishes TimedOut natively — the fold into connect-failed (#56's mapping, matching the then-current taxonomy) splits back out with one match arm. connect-failed's doc drops its timeout claim; a mid-life idle timeout surfaces the same case on stream operations, alongside the A2 closed contract.

not-supported(string) — and D16's latitude, recorded

The deployment-profile gap is live today, not theoretical: the deltic host stubs wasi:sockets with the honest error-code.not-supported (its own header says it's the browser host's answer), and the endpoint flattened it into invalid-argument — a capability answer misreported as an argument error. The udp bind path now carries the distinction through typed errors, and the latitude lives at the option definition sites, per the recorded-latitude ladder:

  • udp-bind-addr on a UDP-less deployment: bind fails not-supported.
  • webrtc on a deployment stubbing the channel import: not detected at bind — upgrades never occur and connections stay on their dial path. Written as latitude rather than left implied; a bind-time capability probe would need surface the WebRTC import doesn't have, so the honest contract is the degradation.

in-use(string)

The B4/B6 guards deliberately parked six documented flows on error.other (in-flight read/write refusals, both via-stream claims, finish-under-a-write) — other as load-bearing in documented flows is exactly the smell C14 named. One dedicated case covers the family, in the spirit of the siblings' receiving-via-stream; the payload says which conflict. The via-stream abandonment future stays other — it is not a conflict.

Conformance

  • The absent-peer matrix row pins TimedOut and the wrong-alpn row ConnectFailed (both previously grepped the word "connect", which either case satisfied).
  • The stream-negative probes match in-use exactly instead of sniffing other's message text.
  • The deltic exam's scenario 1 gains the browser-profile probe: a bind with udp-bind-addr set must fail not-supported — the stub's error-code carried through unflattened. Placed after the zero-socket-calls check, since the probe deliberately reaches the stub.

Ordering note: this rode the #58 A10 transition (ComponentException, kind/value envelopes) — the facade and exam edits here follow the new shapes, and stale .deps checkouts needed the usual setup.sh re-run (the #51 lesson, dutifully re-learned).

Verified

just check, just probes, just matrix (15 rows), just exam-deltic (6/6, new probe green), just bench (budgets hold).

Addresses #13 (C14, D16).

lann added 2 commits August 12, 2026 12:57
…ported, in-use

Issue #13 findings C14 and D16. Three failure modes the docs already
described rode cases that misnamed them:

- timed-out(string): a dial the peer never answers, and a relay open
  that never completes, kept their own case instead of folding into
  connect-failed (whose doc no longer claims timeouts) or riding
  error.other from the generic connection-lost mapping. A mid-life
  idle timeout surfaces the same way on stream operations.
- not-supported(string): the deployment-profile latitude (D16) is live
  today — the deltic host stubs wasi:sockets with the honest
  error-code.not-supported, and the endpoint flattened it into
  invalid-argument. The udp bind path now carries the distinction, and
  the latitude is recorded at the option definition sites:
  udp-bind-addr fails bind with not-supported on a UDP-less host;
  a stubbed WebRTC import is not detected at bind and leaves upgrades
  non-functional (written, not implied).
- in-use(string): the B4/B6 guards left error.other load-bearing in
  six documented flows (in-flight read/write refusals, via-stream
  claims, finish under a write). They get the dedicated case, in the
  spirit of the siblings' receiving-via-stream.

Conformance sharpens accordingly: the absent-peer matrix row now pins
TimedOut and the wrong-alpn row ConnectFailed (both previously grepped
the word connect); the stream-negative probes match in-use exactly;
the deltic exam's scenario 1 gains the browser-profile probe — bind
with udp-bind-addr set must fail not-supported, the stub's error-code
carried through unflattened.

Addresses #13 findings C14 and D16.
Issue #13 findings C10, C9 (formats), D15, and the D17 remnant — all
doc rulings, no behavior change.

C10: connect no longer promotes the v0 dial narrowing to contract.
Dial-path selection from addr.addrs is implementation-defined —
prefer, race, or fall back are all conforming — so an upstream-backed
implementation of this surface (which always races) is no longer
non-conformant by construction. This implementation's actual
selection stays recorded where the narrowings live
(endpoint/src/lib.rs); the matrix rows that lean on no-fallback assert
that recorded latitude, not the contract.

C9: transport-addr's string formats are specified — relay is an
http(s) base URL with one-spelling-per-relay guidance (normalization
is implementation-defined beyond the exact string), ip is
dotted-quad or bracketed IPv6 with scope-id support
implementation-defined and unparseable entries ignored for dialing.

D15, resolved as a ruling rather than a declaration: the built
component's import set includes a toolchain wasi 0.2 tail (io, cli,
clocks, filesystem, random — bind's reset and token keys ride
wasi:random through the language's entropy source). Declaring one of
those interfaces in the source world at a pinned version would fight
toolchain drift and split the import in two on mismatch. The world's
doc now states what the world is (the deliberately-bound surface) and
names the artifact's embedded WIT as the authoritative import
manifest.

D17 remnant: read(max: 0) resolving some([]) is documented.

Addresses #13 findings C9, C10, D15, D17.
The contract stops over-promising and under-recording
@lann
lann merged commit 6356b82 into main Aug 12, 2026
1 of 2 checks passed
@lann
lann deleted the error-taxonomy branch August 12, 2026 19:16
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.

2 participants