Shared task
Handle writer errors like other entry errors (#4370)
commit a432466 ↗ · phoenixframework/phoenix_live_view · · committed Aug 14, 2026 · +701 −106 · base cad568e564cd
what a new run launched now would send
Custom Phoenix.LiveView UploadWriter failures (init/1, write_chunk/2, and close/2) do not behave like other upload entry errors. Today a writer failure can drop or hide the entry, leave upload-name registration stuck so a later allow/retry cannot proceed, skip or mishandle progress so the UI never shows {:writer_failure, reason}, treat a server writer failure as a generic client entry error, or otherwise leave the LiveView/upload channels inconsistent — including when writer init fails after the entry is already registered.
Fix writer failures so they are handled like other entry errors end-to-end:
- Retain the failed entry with a visible {:writer_failure, reason} until it is explicitly cancelled (or replaced); do not auto-drop it when the upload channel exits.
- Keep the LiveView process alive; the upload channel should shut down cleanly on writer failure.
- Invoke the upload progress callback with the failed entry so apps can react (including cancelling/disallowing in that callback).
- A failed entry must not be joinable/uploadable again; cancelling the last/failed entry must release the upload name so a new upload can be allowed and succeed.
- Successful sibling entries in the same upload must still be consumable individually while a failed entry remains.
- On the client, when the server reports a writer failure, do not apply the generic entry-error path that clears/errors the entry a second time; leave it pending until cancel removes it from the DOM.
- Writer init failures must report and retain the entry the same way write/close failures do.
Acceptance is behavioral: failed writer entries stay visible with the writer failure until cancelled; LiveView stays connected; cancel + re-allow works; siblings can complete; no crash from writer errors.
Interface contract — the change must expose exactly this surface:
Phoenix.LiveView.UploadConfig.fail_entry/3 (conf, entry_ref, reason): retain the entry, record the error (without duplicating the same error pair), mark the entry so entry_pid is nil and register_entry_upload returns {:error, :disallowed}; unregister_completed_entry must leave a failed entry in place. Upload channel join failures for writer init continue to use %{reason: :writer_error}.
Work only inside this repository checkout. Make the code change the task
describes, keeping the diff focused — no drive-by refactors.
When you are done, leave your changes committed or in the working tree;
they are collected automatically.
Stay on this snapshot checkout (`task/ycb_phoenix_live_view_ca432466a4f91`). Never checkout, pull, or rebase onto `main`. That branch is a README-only orphan.
Stay on this HEAD. Do not fetch another default branch. Push only on the Cursor-created `crazy-cursor/…` side branch from this HEAD.Some past runs of this task were launched with a different prompt (the prompt template changed since, or those runs predate this benchmark's stored prompt). Each run persists the exact prompt it sent at launch — that per-launch record is the audit trail; this page shows only the current one.
| Run | Model | Verdict |
|---|---|---|
| Aug 17, 12:59 UTC · completed | claude-opus-5 | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5 | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5 |
Powered by YourCodingBench — benchmark coding models on your own repo's commits. sign in
| Aug 17, 12:59 UTC · completed | claude-opus-5-low | FAIL |
| Aug 17, 12:59 UTC · completed | claude-opus-5-low | FAIL |
| Aug 17, 12:59 UTC · completed | claude-opus-5-low | FAIL |
| Aug 17, 12:59 UTC · completed | claude-opus-5-medium | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5-medium | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5-medium | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5-xhigh | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5-xhigh | PASS |
| Aug 17, 12:59 UTC · completed | claude-opus-5-xhigh | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5 | PASS |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5 | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5 | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-low | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-low | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-low | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-medium | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-medium | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-medium | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-xhigh | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-xhigh | FAIL |
| Aug 17, 12:59 UTC · completed | claude-sonnet-5-xhigh | FAIL |
| Aug 17, 12:59 UTC · completed | composer-2.5 | FAIL |
| Aug 17, 12:59 UTC · completed | composer-2.5 | FAIL |
| Aug 17, 12:59 UTC · completed | composer-2.5 | FAIL |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash-low | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash-low | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash-low | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash-medium | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash-medium | timeout |
| Aug 17, 12:59 UTC · completed | gemini-3.7-flash-medium | timeout |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol | PASS |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol | PASS |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-high | judge failed |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-high | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-high | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-low | PASS |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-low | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-low | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-none | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-none | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-none | FAIL |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-xhigh | PASS |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-xhigh | PASS |
| Aug 17, 12:59 UTC · completed | gpt-5.6-sol-xhigh | PASS |
| Aug 17, 12:59 UTC · completed | grok-4.6 | timeout |
| Aug 17, 12:59 UTC · completed | grok-4.6 | PASS |
| Aug 17, 12:59 UTC · completed | grok-4.6 | PASS |
| Aug 17, 12:59 UTC · completed | grok-4.6-low | timeout |
| Aug 17, 12:59 UTC · completed | grok-4.6-low | FAIL |
| Aug 17, 12:59 UTC · completed | grok-4.6-low | FAIL |
| Aug 17, 12:59 UTC · completed | grok-4.6-medium | timeout |
| Aug 17, 12:59 UTC · completed | grok-4.6-medium | FAIL |
| Aug 17, 12:59 UTC · completed | grok-4.6-medium | FAIL |
| Aug 17, 12:59 UTC · completed | grok-4.6-xhigh | timeout |
| Aug 17, 12:59 UTC · completed | grok-4.6-xhigh | PASS |
| Aug 17, 12:59 UTC · completed | grok-4.6-xhigh | PASS |
Binary verdicts from the pinned judge (D27). Full attempt detail — candidate diff, transcript, timings — lives on each run page's score matrix.