Skip to content

fix(reporter): contain JSONReporter writer panics as transport failures - #77

Merged
bketelsen merged 1 commit into
mainfrom
cockpit/worker-be311dec9c123834
Aug 30, 2026
Merged

fix(reporter): contain JSONReporter writer panics as transport failures#77
bketelsen merged 1 commit into
mainfrom
cockpit/worker-be311dec9c123834

Conversation

@bketelsen

Copy link
Copy Markdown
Contributor

Summary

JSONReporter.emit recovered a panic from the underlying io.Writer during
the primary json.Encoder.Encode call, but mislabeled it as a Details
encoding failure and routed it through the encoding-error fallback — and the
fallback's own Encode call had no panic recovery at all, so a writer panic
there could escape emit() and crash the caller.

Adds writerPanicGuard, a thin io.Writer wrapper installed around the
writer at NewJSONReporter construction, that recovers a panic from Write
and converts it into an ordinary error before it ever reaches the encoder.
Both the primary and fallback encode paths already treat a returned writer
error correctly (discard it, latch failed, drop later events), so the
writer-panic case now flows through that same existing, tested path instead
of a separate one. A panicking Details json.Marshaler is unaffected: that
panic happens during in-memory marshaling, before Write is ever called, so
encodeRecover still owns it.

Checks

  • make check — gofmt leaves no diff, golangci-lint run
    (.golangci.yml) clean, go test -v ./... green (unit + tests/e2e)
  • go test -race -short ./... green
  • go.mod still declares no dependencies (stdlib only)
  • New or changed behavior has focused tests, including failure paths;
    exact output changes update docs/specs/reporter-package.md

Docs housekeeping

  • AGENTS.md, docs/design/overview.md, docs/specs/* updated for
    behavior or convention changes (docs/specs/reporter-package.md)
  • New docs started from their category's TEMPLATE.md and indexed in
    docs/README.md
  • New significant decision recorded as an ADR first, in this PR
  • Conformance aliases (ADR-0001) untouched — canonical targets edited
    instead

Protected boundaries

N/A — no .github/workflows/**, .goreleaser.yaml, .svu.yaml, or
policies/agent-governance.json touched.

Verification

  • node scripts/check-docs.mjs green:
    ok   docs_index_coverage: 1.000 (required 1)
    ok   link_integrity: 1.000 (required 1)
    ok   symlink_resolution: 1.000 (required 1)
    checked: 12 docs, 153 links, 9 symlinks
    
  • Checked against the
    PR review rubric

Risk classification

Moderate. This changes the failure-handling behavior of a shipped public
constructor (NewJSONReporter): a writer panic is now contained and reported
identically to a writer error instead of being mislabeled or, on the
fallback path, potentially escaping to the caller. No public API signature
changed, no protected boundary touched, and the change is narrowly scoped to
reporter/json.go with focused new tests covering both the primary and
fallback panic paths.

A panic raised by the underlying io.Writer during the primary JSON
encode was mislabeled as a Details encoding error (routing it through
the encoding-error fallback), and the same panic during the fallback
encode had no recovery at all and could escape to the caller.
writerPanicGuard converts a Write panic into an ordinary error before
it reaches emit(), so both paths latch the reporter's existing failed
state like any other writer error.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@bketelsen
bketelsen marked this pull request as ready for review August 30, 2026 02:12
@bketelsen
bketelsen added this pull request to the merge queue Aug 30, 2026
Merged via the queue into main with commit 8b653d1 Aug 30, 2026
8 checks passed
@bketelsen
bketelsen deleted the cockpit/worker-be311dec9c123834 branch August 30, 2026 02:17
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