Fix BC-10091763201: send turbo-stream Accept from autosave to stop 406#2979
Fix BC-10091763201: send turbo-stream Accept from autosave to stop 406#2979jeremy wants to merge 1 commit into
Conversation
Root cause: submitForm() built a FetchRequest with no responseKind, so @rails/request.js defaulted to Accept: text/html. The drafted-card autosave POSTs (with _method=patch) to CardsController#update, whose respond_to only registers turbo_stream and json — no html — so Rails raises UnknownFormat and returns 406 Not Acceptable on every autosave. (No data loss: @card.update! commits before respond_to raises; what's lost is the turbo_stream UI update and the log fills with 406s.) Fix: pass responseKind: "turbo-stream" so the request declares the Accept header the action serves. Sole caller is the draft autosave, so this also lets the update.turbo_stream.erb side effects (draft container morph, closure toggle) actually apply after each save, as intended. Card: https://app.basecamp.com/2914079/buckets/27/card_tables/cards/10091763201
There was a problem hiding this comment.
Pull request overview
This PR fixes drafted-card autosave requests returning 406 Not Acceptable by ensuring autosave form submissions advertise they accept Turbo Stream responses, matching CardsController#update’s respond_to formats.
Changes:
- Update
submitForm()to passresponseKind: "turbo-stream"when constructingFetchRequest, so the request uses the correctAcceptheader and receives theupdate.turbo_streamresponse.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7aa24d6639
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const request = new FetchRequest(form.method, form.action, { | ||
| body: new FormData(form) | ||
| body: new FormData(form), | ||
| responseKind: "turbo-stream" |
There was a problem hiding this comment.
Prevent stale autosave streams from clobbering edits
With this option, request.js automatically renders the CardsController#update turbo-stream response, whose first stream morph-replaces the whole card_container. In the draft autosave flow the 3s debounce can fire while the user keeps typing, and auto_save_controller has no in-flight/stale-response guard; if the response for an older snapshot returns after newer keystrokes, the morph renders that older server state back into the same draft form. Unlike the normal edit form, the draft form has no local-save restore hook, so those newer edits can be overwritten or re-saved as the old value on slow connections.
Useful? React with 👍 / 👎.
|
🤖 Independent verification while chasing card 10036823881 (Firefox paste/title-focus report): reproduced the 406 autosave storm locally (Playwright Firefox, real table paste into a draft card — One caveat found during verification: with the fix applied, the now-rendered |
Summary
Fixes BC-10091763201 — POST to
/cards/:idreturns 406 Not Acceptable on drafted-card autosave.Problem
Typing in a new/drafted card's title or description, then blurring / pressing Enter / waiting for the 3s debounce, fires an autosave that 406s. The comment editor is unaffected (it submits through Turbo's own form machinery).
Solution
app/javascript/helpers/form_helpers.js— passresponseKind: "turbo-stream"to theFetchRequest.Root Cause
submitForm()constructed theFetchRequestwith noresponseKind, so@rails/request.jsdefaulted toAccept: text/html. The autosave POST (with hidden_method=patch) routes toCardsController#update, whoserespond_toregisters onlyturbo_streamandjson— nohtml— so Rails raisesActionController::UnknownFormat→ 406. Every other@rails/request.jscaller in the app already passesresponseKind: "turbo-stream".No data loss:
@card.update!commits beforerespond_toraises. What was actually lost is theupdate.turbo_stream.erbside effects (draft-container morph, closure toggle) — which now apply correctly after each save — plus a 406/UnknownFormat on every drafted-card autosave in the logs.Origin
The missing
responseKinddates to4121f68f7"Auto-save edits to bubble title" (Kevin McConnell) — a latent gap. It was masked whileCardsController#updateended inredirect_to @card(a 302 an html-Accept fetch happily followed); it started 406ing whenb05ecb780(Mike Dalessio, 2025-11-22) removed the redirect and moved to a turbo_stream template. So: JS-side latent gap, surfaced by a server-side change.Scope
submitFormhas exactly one caller —auto_save_controller.js, attached only to the drafted-card form — so no other flow is affected.Testing
Bug Card
https://app.basecamp.com/2914079/buckets/27/card_tables/cards/10091763201