fix: only treat structural issues as fatal in applyRuntimeStateDelta#135
fix: only treat structural issues as fatal in applyRuntimeStateDelta#135pzysvip99999 wants to merge 2 commits intoNarcooo:masterfrom
Conversation
…ors from crashing the pipeline The state validator was throwing an uncaught exception when the LLM output contains invalid JSON characters (e.g. control chars, unescaped sequences), causing the entire write pipeline to crash with 'State validator returned invalid JSON'. This wraps the entire function in a try-catch so that any such errors are returned as a validation issue rather than crashing.
Filter warnings (missing_state_change, unsupported_change, temporal_impossibility, validator_crash) before throwing, allowing the pipeline to continue when the LLM reports content-level contradictions that are not structural errors.
JiwaniZakir
left a comment
There was a problem hiding this comment.
The decision to include validator_crash in the non-fatal allowlist in state-reducer.ts is worth scrutinizing. A validator_crash means validateRuntimeState threw an unexpected exception mid-execution — validation did not complete, so the returned issues array is incomplete and we have no actual guarantee about the validity of next. Treating this as non-fatal and returning next anyway could silently propagate a structurally broken state, which seems worse than the validator crashing loudly.
The hardcoded string array in the filter (["missing_state_change", "unsupported_change", "temporal_impossibility", "validator_crash"]) is also fragile — if a new non-structural issue code is added to the validator, it will be treated as fatal by default, requiring a second PR to update this list. Consider deriving this from a typed constant or enum shared with the validator, so exhaustiveness can be checked at compile time.
Finally, there's no test coverage shown for the validator_crash path introduced in state-validator.ts. A test that forces parseOrIssue to throw (e.g., by passing a getter that throws on a schema property) would confirm the catch block returns the expected issue shape and that applyRuntimeStateDelta doesn't throw in that scenario.
Fix: only treat structural issues as fatal in applyRuntimeStateDelta
Problem
applyRuntimeStateDelta()instate-reducer.tscallsvalidateRuntimeState()and throws wheneverissues.length > 0, treating both fatal structural errors (duplicate hook IDs, malformed JSON) and warning-level content contradictions (missing state changes, unsupported changes) as fatal. This causes the pipeline to crash when the LLM reports amissing_state_changeorunsupported_changewarning — even though these are legitimate content-level observations, not structural failures.Fix
Filter issues into fatal vs warning before throwing:
Together with PRs #132, #133, #134
state/state-validator.tssettler-delta-parser.tssanitizeJSON()fixes root cause of parse failuresagents/state-validator.tsparseResult()/validate()return graceful result on errorsstate/state-reducer.tsAfter all four PRs: the write pipeline is resilient to both crashes (JSON parse/validation errors) and content-level contradictions (warnings), while still stopping on genuine structural errors.