{"record":{"id":"4892c475a4ddd9ba","repo":"windmill-labs/windmill","slug":"this-page-has-changes-that-are-not-valid-json-fix","errorCode":null,"errorMessage":"This page has changes that are not valid JSON. Fix them first.","messagePattern":"This page has changes that are not valid JSON\\. Fix them first\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/sessions/pageDrawerSession.ts","lineNumber":50,"sourceCode":"\t\tObject.entries(TRIGGER_PAGES).map(([kind, p]) => [\n\t\t\tp.path,\n\t\t\t`trigger_${kind as TriggerKind}` as UserDraftItemKind\n\t\t])\n\t)\n}\n\n// Push the drawer's pending autosave and refuse to leave if it did not land: `flush`\n// reports a failed or conflicting POST through its state rather than by throwing, so\n// routing regardless would open the preview on the server's older draft while the drawer\n// the user is looking at still holds the edit. The flush is the explicit kind, saving even\n// with auto-save off: asking for a session is asking for the edit to come along.\nasync function flushOrRefuse(query: Parameters<typeof UserDraftDbSyncer.flush>[0]): Promise<void> {\n\t// Before the save, not after: text that does not parse never reached the draft, so\n\t// leaving now would open the session on the last value that did and drop the buffer\n\t// with the drawer — and saving first would write that stale value on the way to\n\t// refusing. The editors were materialised before this call, so the check is current.\n\tif (anyEditorUnparseable()) {\n\t\tthrow new Error('This page has changes that are not valid JSON. Fix them first.')\n\t}\n\tawait UserDraftDbSyncer.flush(query)\n\tif (UserDraftDbSyncer.getConflict(query).conflict) {\n\t\tthrow new Error(\n\t\t\t'This draft has a newer conflicting version on the server. Resolve it here before opening a session.'\n\t\t)\n\t}\n\tconst { state, failureMessage } = UserDraftDbSyncer.getState(query)\n\tif (state === 'failed') {\n\t\tthrow new Error(\n\t\t\t`Saving the latest draft failed (${failureMessage ?? 'unknown error'}). Retry before opening a session.`\n\t\t)\n\t}\n}\n\n// How each page addresses a row in its hash. Resources route theirs through an extra\n// segment; every other page names the path directly.\nconst drawerHashFor = (pagePath: string, itemPath: string) =>","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/sessions/pageDrawerSession.ts#L32-L68","documentation":"flushOrRefuse is the pre-flight gate before opening a session from the page drawer: it refuses to save if any editor on the page currently holds text that is not valid JSON. Throwing before flushing guarantees no stale or broken buffer is written and the session doesn't open on lost changes.","triggerScenarios":"Calling pageDrawerSession's open/flush path (via pageDrawerSessionSource) while anyEditorUnparseable() reports an editor with invalid JSON in its buffer.","commonSituations":"User typed a partial JSON edit (trailing comma, unclosed brace) in a resource/script arg editor and immediately clicked 'open session'; programmatically set editor text that wasn't validated.","solutions":["Fix the JSON in the flagged editor until it parses, then retry","Discard the invalid editor changes before opening the session","Use the editor's format/lint indicator to locate the syntax error"],"exampleFix":"// before\n{ \"a\": 1, }\n// after\n{ \"a\": 1 }","handlingStrategy":"validation","validationCode":"if (anyEditorUnparseable()) return; // don't attempt to open a session\nawait openSession(query)","typeGuard":"function isParseableJson(s: string): boolean { try { JSON.parse(s); return true } catch { return false } }","tryCatchPattern":"try { await openSession(query) } catch (e) { if (/not valid JSON/.test(String(e))) focusFirstUnparseableEditor(); else throw e }","preventionTips":["Validate editor content on every keystroke and disable 'open session' while invalid","Run JSON.parse before staging any editor text programmatically","Show inline syntax errors so users fix them before saving"],"tags":["json","validation","sessions","drafts"],"backgroundTag":"invalid-json","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}