go-queue-failure-reason-persistence
I've written the solution to /workspace/solution.md. Here's a recap of what it contains and the one environment caveat you should know about.
The source repository for this problem is not mounted in this environment — /workspace contains only problem.json, and a filesystem-wide search for MarkFailed, entryToWire, queue_entries, or queue.sql returned no Go source. So I could not apply the patch to a live tree. I reconstructed the landed fix from the specification and empirically validated the two non-obvious mechanisms with runnable checks.
/workspace/solution.mdMarkFailed discarded reason, the column didn't exist, scanEntry never read it, all four explicit SELECTs omitted it, and the wire/OpenAPI layer never exposed it. Also ReapStale failed rows with no reason.failure_reason TEXT NOT NULL DEFAULT '' appended to queue.sqlALTER TABLE ADD COLUMN in Open() swallowing only duplicate column nameMarkFailed sets failure_reason = ? through a rune-boundary-safe 4000-byte capFailureReasonEntry.FailureReason + appended scan argGet / List / Dequeue / findPendingDuplicate without reorderingentryToWire with json:"failure_reason,omitempty"ReapStale stamps a stale-reap reasonQueueEntry.failure_reason using inline scalars only, asserted via api.JSONBytes()ReapStale assertion, end-to-end curl (including has("failure_reason") == false for successful entries), and the parsed-spec assertion.capFailureReason on 3-byte runes returned 3999 bytes (trimmed one partial byte), on 4-byte runes returned exactly 4000, both valid UTF-8, short strings untouched.duplicate column name: <col> on the second ALTER TABLE, confirming the substring match isDuplicateColumn must use; inserts/reads of the new column succeed.# Evidence - Problem class: go-queue-failure-reason-persistence - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-15T01:52:45.307Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Solve failure reason was discarded: Queue.MarkFailed(ctx,id,reason) had an underscore-discard of reason and queue_entries had no failure_reason column, so GET /api/v1/queue/{id} showed status=failed with no why. Fix that landed (off-by-one DF-OFF-BY-ONE-4): add failure_reason TEXT NOT NULL DEFAULT to queue.sql schema + defensive ALTER TABLE ADD COLUMN in Open() ignoring duplicate-column errors (mirrors required_tools migration); MarkFailed SET failure_reason=? with a rune-boundary-safe 4000-byte cap; append &e.FailureReason to scanEntry and to EVERY explicit SELECT column list (Get/List/Dequeue/findPendingDuplicate) without reordering; expose via entryToWire with omitempty; stamp ReapStale rows with a stale-reap reason; document in OpenAPI QueueEntry schema. Watch: pkg/api YAML parser silently truncates on >- folded scalars \u2014 use inline scalars only, verify via api.JSONBytes().", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-queue-failure-reason-persistence", "provider": "openrouter", "solved_at": "2026-09-15T01:52:45.308Z", "version": ""}