windmill-labs/windmill · error · Error
Invalid JSON after replacement: ${message}
Error message
Invalid JSON after replacement: ${message} What it means
After applying textual replacements to a flow's JSON representation, the code re-parses the result with JSON.parse. If parsing fails, the replacement produced syntactically invalid JSON (e.g. broke braces/quotes), so the operation is aborted with the parser's message appended. This protects the flow draft from being overwritten with unparseable content.
Source
Thrown at frontend/src/lib/components/copilot/chat/global/core.ts:5236
// content is preserved through the patch via the InlineScriptSession; the
// model uses set_flow_module_code to change inline script bodies.
const base = await loadFlowDraftValue(path, ctx.workspace)
const session = createInlineScriptSession()
const editable = buildEditableFlowJson(flowDraftAsEditableInput(base.flow), session)
const currentJson = JSON.stringify(editable)
const updatedJson = findAndReplace(
currentJson,
oldString,
newString,
replaceAll,
'compact flow JSON'
)
let parsedValue: unknown
try {
parsedValue = JSON.parse(updatedJson)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
throw new Error(`Invalid JSON after replacement: ${message}`)
}
const aiProviders = await getAiAgentProviderCatalogFor(
ctx.workspace,
(parsedValue as { modules?: unknown } | null)?.modules
)
const aiProviderWarnings: string[] = []
const patchedEditable = validateEditableFlowJson(parsedValue, { aiProviders, aiProviderWarnings })
const newFlowValue = applyEditableFlowJsonToFlow(base.flow.value, patchedEditable, session)
finalizeUnresolvedInlineScripts(newFlowValue)
const result = await writeFlowDraft(
{
path,
summary: base.summary,
flow: {
...base.flow,
value: newFlowValue,View on GitHub (pinned to e474e8803c)
Solutions
- Make the replacement text JSON-escaped (escape quotes/backslashes/newlines) and repeat the patch.
- Choose a search snippet that lies entirely within a single JSON string value, not across structural tokens.
- Use the structured write_flow tool instead of textual replacement for structural changes.
Example fix
// before
replace('"code": "old"', '"code": "say "hi""') // unescaped quotes break JSON
// after
replace('"code": "old"', '"code": "say \\"hi\\""') Defensive patterns
Strategy: validation
Validate before calling
function canPatchSafely(json: string, search: string, replace: string): boolean {
const updated = json.replace(search, replace)
try { JSON.parse(updated); return true } catch { return false }
} Try / catch
try {
await patchFlowJson(args)
} catch (e) {
if (String(e.message).startsWith('Invalid JSON after replacement:')) {
// re-escape replacement text or switch to write_flow
} else throw e
} Prevention
- JSON-escape quotes, backslashes and newlines inside replacement strings.
- Keep search snippets inside a single JSON string value, never across structural tokens.
- Dry-run the replacement locally with JSON.parse before sending.
- Prefer structured flow tools (write_flow / patch_flow_json) over raw text replacement.
When it happens
Trigger: A patch-style replace operation over a flow JSON string yields text that JSON.parse rejects — mismatched quotes, trailing commas, truncated structure after the replaced snippet.
Common situations: The replacement text itself contains unescaped quotes or newline characters; the searched snippet spanned a structural boundary (comma, brace) and its replacement removed or duplicated structural tokens; the model replaced JSON with pseudo-JSON prose.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid JSON for ${field}: ${errorMessage}
- Invalid JSON after replacement: ${message}
- Invalid JSON for ${field}: ${message}${hint}
- Failed to parse or apply JSON: ${error instanceof Error ? er
- Failed to parse flow value: {}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/c7ec1829231dc0b6.
Report an issue: GitHub.