windmill-labs/windmill · error · Error

Failed to parse or apply JSON: ${error instanceof Error ? er

Error message

Failed to parse or apply JSON: ${error instanceof Error ? error.message : String(error)}

What it means

This wraps any failure raised while parsing and applying a JSON-based flow edit in FlowAIChat.svelte. The original error's message is appended so the developer sees the underlying cause (JSON.parse failure, schema mismatch, or an error thrown by the apply logic).

Source

Thrown at frontend/src/lib/components/copilot/chat/flow/FlowAIChat.svelte:245

					}
				}

				const result = applyFlowJsonUpdate(flowStore.val, inlineScriptSession, {
					modules,
					schema,
					preprocessorModule,
					failureModule,
					groups,
					notes,
					settings
				})

				// Refresh the state store to update UI
				refreshStateStore(flowStore)
				await acceptPendingFlowEditsIfEnabled(true)
				return result
			} catch (error) {
				throw new Error(
					`Failed to parse or apply JSON: ${error instanceof Error ? error.message : String(error)}`
				)
			}
		}
	}

	$effect(() => {
		if (
			!aiChatManager.autoAcceptEditsActive &&
			$currentEditor?.type === 'script' &&
			selectedId &&
			diffManager?.moduleActions[selectedId]?.pending &&
			$currentEditor.editor.getAiChatEditorHandler()
		) {
			const moduleLastSnapshot = diffManager.beforeFlow
				? (findModuleInFlow(diffManager.beforeFlow.value, selectedId) ?? undefined)
				: undefined
			const content =

View on GitHub (pinned to e474e8803c)

Solutions

  1. Read the wrapped inner message to identify the real failure (parse vs apply)
  2. Retry the generation asking the model for strict raw JSON without code fences
  3. Validate the JSON against the flow schema before applying; add a pre-parse sanitization step

Example fix

// before
throw new Error(`Failed to parse or apply JSON: ${error instanceof Error ? error.message : String(error)}`)
// after
const raw = text.replace(/^```(?:json)?\n?|\n```$/g, '')
let parsed
try { parsed = JSON.parse(raw) } catch (e) {
  throw new Error(`Invalid JSON from model: ${e.message}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

let parsed
try { parsed = JSON.parse(rawText) } catch (e) { throw new Error(`Model returned invalid JSON: ${e.message}`) }
if (typeof parsed !== 'object' || parsed === null) throw new Error('Model JSON is not an object')

Type guard

function isJsonObject(v: unknown): v is Record<string, unknown> { return typeof v === 'object' && v !== null && !Array.isArray(v) }

Try / catch

try { result = applyFlowJson(raw) } catch (error) { console.error('flow json apply failed', error); sendUserToast(`Failed to parse or apply JSON: ${error.message}`, true) }

Prevention

When it happens

Trigger: The AI tool returns JSON that fails to parse (truncated/malformed output), or the parsed document fails during application (invalid flow structure, store update failure) inside the try block ending at `refreshStateStore(flowStore)` / `acceptPendingFlowEditsIfEnabled(true)`.

Common situations: Model emits markdown-fenced or truncated JSON; large flows hit output token limits; the apply step references modules/paths absent from the current flow.

Understand the failure class

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/bd8e23bd29621eb6. Report an issue: GitHub.