picatz / picatz/flowstate

The error pipeline: one failure, every surface, no garbling

Open
#184 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

design engine kind/design-record
Dominant language
Go
Stars
9
Forks
0
Avg merge
3h 3m
Merged PRs (30d)
509

Description

A sql plugin's "connection refused" crosses five boundaries — plugin → wire → host classification → history → CLI/LSP/JSON — and the garbling failure mode at every hop is the same: flattening structure into a string too early, then wrapping it again ("step x: plugin sql: step x: rpc error: ..."). This issue records the rule that prevents it and the two pieces that complete it. Companion to #181's author-time diagnostics tiers; this is the runtime half.

The rule: structure travels, text is rendered last

Every hop passes the structured form — kind, retryability, retry-after, message, source — and only the final surface renders text (the #164 discipline applied to failures). What already holds, mostly from this week: the SDK constructors are the plugin's typed vocabulary (Unavailable/Conflict/OutcomeUnknown/UnavailableAfter…); they cross the wire as a connect code plus a typed ExecuteResponse detail, never string convention; the host classifies from the ORIGINAL error before scrubbing (the #160 fix — redaction can no longer destroy classification); error text is spelled identically on both drivers (invariant, shared cases); machine surfaces render from structure.

Gap 1: a round-trip conformance test plugins inherit for free

In the SDK: classified error → wire → host TaskError → rendered text and JSON, asserting kind/retryability/hint survive and the message appears EXACTLY once (double-prefixing is garbling too). A plugin author only chooses a constructor; the conformance test is what keeps "my errors read correctly everywhere" true as plugins multiply. Containment shapes included (%v/%+v/%#v/%s on the error, a struct holding it, a slice) so the secrets rules ride the same test.

Gap 2: source positions on runtime failures

Today a runtime failure names its step id; the file position exists only at compile time. If the compiled spec carries a compact, optional, bytes-bounded source map (step id → file/line/column), then flow get on a failed run can say: step "lookup" (workflow.yaml:23): sql: connection refused — retryable, next attempt in 30s. An agent reading the JSON gets the position machine-readably — production failure straight back to the editor line. One-artifact philosophy: the position was known once, at compile; carrying it forward beats every consumer re-deriving it. Bounds: the map counts against CheckSpecSize; positions are advisory (absent on hand-built specs, which is fine — invariant 10 add-only).

Burden placement

Plugin authors: choose a constructor. Host, once: classification, scrubbing order, both-driver text, JSON shape, position attachment. The conformance test enforces the contract. sql (#181) is the first beneficiary; git's Conflict classification is the existing proof the vocabulary works end to end (a Flowfile can dispatch on "someone else pushed first" vs "this broke").

Sequencing: both pieces Sonnet-sized, after the current wave; the source map wants a slice of its own (proto field + parser emission + get/watch rendering + LSP jump-to-step).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the SDK constructors through wire encoding, host classification, and the final CLI/LSP/JSON renderers. Establish the round-trip conformance test first, then inspect compiled-spec handling for the optional source map and its flow get/watch and LSP consumers. Done means structured errors survive every boundary without garbling, and source positions remain bounded, optional, and machine-readable.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend, cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.