Skip to content

fix(core): SIGPIPE-immune account resolution under pipefail#60

Merged
webdevtodayjason merged 1 commit into
mainfrom
fix/w65-resolver-sigpipe
Jun 12, 2026
Merged

fix(core): SIGPIPE-immune account resolution under pipefail#60
webdevtodayjason merged 1 commit into
mainfrom
fix/w65-resolver-sigpipe

Conversation

@webdevtodayjason

Copy link
Copy Markdown
Owner

Latent since v3.3.13 interacted with bin/subctl's pre-existing set -uo pipefail: the resolver's early-exit awk SIGPIPEs subctl_list_accounts mid-write, so the pipeline exits 141 even though the alias was printed and captured — || subctl_die "unknown account" fires on a successful lookup. Position-dependent race (last-row aliases always safe, mid-file aliases reliably fail), which is why every same-day proof passed. Surfaced by W6.5's codex dry-run proofs (openai-jason, row 4/7: 5/5 fail on pristine main).

Fix: buffer-once + herestring in subctl_resolve_alias (all three passes) and subctl_account_field; early-exit semantics and the v3.3.13 three-pass contract unchanged. Other list_accounts consumers audited — no early-exit awk, untouched.

Orchestrator-verified: 9/9 core.test.ts (4 new tests mirror bin/subctl's pipefail env on a 50-row early-target roster; worker red-proofed them against pristine core.sh — 3 fail there); live 5/5 repro → 5/5 clean on the original failing command; suite failure set byte-identical to baseline.

🤖 Generated with Claude Code

…low-up)

`subctl teams openai-codex -a openai-jason --dry-run` failed with
'unknown account: openai-jason' on pristine main (5/5). bin/subctl sets
`set -uo pipefail`; subctl_resolve_alias piped the slow
subctl_list_accounts producer (5 _subctl_trim command substitutions per
row) into an early-exit awk. awk's exit closed the pipe mid-write, the
producer took SIGPIPE, pipefail turned the pipeline status into 141, and
`resolved=$(subctl_resolve_alias …) || subctl_die` fired even though
the alias had already been printed and captured. Position-dependent:
early/mid-file aliases always lost the race; last-row aliases always won.

Fix: buffer the roster once per call (local all=$(subctl_list_accounts))
and feed every early-exit awk via herestring — no pipe, no SIGPIPE, no
141. Applied to both exposed helpers (subctl_resolve_alias, all three
passes, and subctl_account_field); the remaining list_accounts consumers
in core.sh (accounts_by_provider, count_by_provider) have no early exit
and are unaffected. v3.3.13 three-pass semantics unchanged — the five
pre-existing core.test.ts contract tests stay green untouched.

Regression tests mirror bin/subctl's exact environment: `set -uo
pipefail`, a 50-row roster with the target on row 1 (deterministic
race), 5 repeats per lookup, plus the exact caller shape that died
(capture || die). Proven to catch the bug: 3/3 new lookup tests fail on
pristine core.sh, 0 fail on the fix; manual repro went 5/5 → 0/5.

Gate: bun test lib providers dashboard/__tests__ — failure set
byte-identical to pristine origin/main baseline (22 fail / 3 errors,
known environmental + cli.test.ts set); +4 new tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@webdevtodayjason
webdevtodayjason merged commit 562b774 into main Jun 12, 2026
@webdevtodayjason
webdevtodayjason deleted the fix/w65-resolver-sigpipe branch June 12, 2026 01:07
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