fix(sync): prevent whitespace-only board names from blocking sync - #2282
Open
RodriSanchez1 wants to merge 1 commit into
Open
RodriSanchez1 wants to merge 1 commit into
RodriSanchez1 wants to merge 1 commit into
Conversation
A board name of " " passes the TileEditor submit guard and Swagger validation, but Mongoose applies its trim setter before the required validator, so the value becomes "" and the save is rejected. The board stays PENDING and is re-pushed on every sync cycle indefinitely. - Guard disableSubmit on the trimmed label so whitespace-only labels cannot create a folder board. - Restore a DEFAULT_BOARD_NAME fallback in extractBoardName and treat whitespace-only name/nameKey values as missing. - Trim userName before the author fallback, which fails identically. - Record the API's response status and error detail on pushBoard exceptions; the axios message alone does not name the failing field. Refs #2281 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the sync-blocking half of #2281.
Problem
A board whose
nameis whitespace-only (" ") is accepted everywhere on the way out and rejected at the last step:TileEditor.component.js:532—disableSubmit={!currentLabel}correctly blocks'', but' 'is truthy, so Save is enabled.handleLabelChangeclearslabelKey, so the folder board is created withname: ' ',nameKey: ''.extractBoardNamereturnsboard.nameunchanged, because' 'is truthy.swagger.yaml:1522-1532) declaresnameasrequired/type: stringwith nominLength—requiredmeans the key is present, not non-empty — so it passes.Board.js:8-12) hastrim: true, and the trim setter runs before therequiredvalidator.' 'becomes''and the save fails.Result: 409 from
createBoard, 500 fromupdateBoard, and becauseUPDATE_BOARDsetsPENDINGbefore the call and the catch only logs, the board is re-pushed every sync cycle forever.authorfails identically —transformBoardForUserusedauthor: userName || userEmail, and a display name of' 'is truthy, survives the||, and dies at the sametrim+requiredpair.Changes
TileEditor.component.js—disableSubmit={!currentLabel || !currentLabel.trim()}. Covers both the create (Board.container.js:588) and edit (:1172) paths, since both readtile.labelbehind this button. Deliberately not trimming inhandleLabelChange, which would fight the user mid-typing.Board.utils.js—extractBoardNametreats whitespace-onlynameandnameKeysegments as missing and falls back toDEFAULT_BOARD_NAME;transformBoardForUsertrimsuserNamebefore the||.Board.constants.js—DEFAULT_BOARD_NAME = 'Untitled Board', the same string used before 78866f6. A plain constant rather than an i18n message becauseextractBoardNamehas nointlin scope; localizing it is a signature change worth doing separately.Board.actions.js—pushBoardexceptions now carrystatusandapiError. The API already returns the exact Mongoose message (board.js:38,board.js:262) naming the failing field, but the raw axios rejection's.messageis only"Request failed with status code 500", so that detail was being discarded at the client boundary.Scope — what this does not do
Existing affected boards are not repaired. The
extractBoardNamefallback only runs viatransformBoardForUser, which applies to default/no-email boards. A user-owned board already in localStorage with a whitespace name goes straight toupdateApiBoardand will still fail on every cycle. The fix that would cover it — trimming at the wire inAPI.createBoard/API.updateBoard— was intentionally deferred, and is tracked as an open item on #2281.The retry loop is untouched. Any permanently-rejected board is still re-pushed indefinitely. That needs an attempt counter in
syncMetaand interacts with the graduation logic inclassifyBoardsForPush, so it warrants its own change.One board remains unexplained. The originally-reported board reads
peoplein the DB, which derives fromnameKey: cboard.symbol.peopleand is non-blank under every path examined. No code path was found that blanks it. The telemetry change should settle whether it is failing onnameorauthoron the next sync cycle from an affected user — so please don't read a drop inpushBoardexceptions as proof the diagnosis was complete.Also worth noting: commit 78866f6 (
return ''inextractBoardName) is not the regression. That branch needs a board with neithernamenornameKey; all 44 default boards inboards.jsoncarry anameKeyderiving a non-blank name, and the tile path always supplies a truthyname. It was a latent hazard, now closed by the fallback, but the live bug is whitespace.Testing
eslintclean on all four files. No existing test asserts ondisableSubmit, ontrackSyncException'spushBoardproperties, or onextractBoardName/transformBoardForUser— those two helpers have no direct coverage today, which is a gap worth filling.🤖 Generated with Claude Code