{"record":{"id":"f1f5ef81758e87c1","repo":"shareAI-lab/learn-claude-code","slug":"cached-agent-output-failed-schema-validation-err","errorCode":null,"errorMessage":"cached agent output failed schema validation: {err}","messagePattern":"cached agent output failed schema validation: (.+?)","errorType":"validation","errorClass":"WorkflowInputError","httpStatus":null,"severity":"error","filePath":"s16_workflow_runtime/code.py","lineNumber":469,"sourceCode":"    def log(self, message):\n        \"\"\"Emit a workflow_log progress line.\"\"\"\n        self.task.progress_event(\"workflow_log\", message=message)\n\n    async def agent(self, prompt, schema=None, label=None, phase=None):\n        \"\"\"Spawn one subagent. With a schema, force StructuredOutput + validate\n        (retry once). On resume, a cached key short-circuits the run.\"\"\"\n        label = label or (prompt[:24] + \"...\")\n        self._limits.claim_agent()\n        if self.budget.remaining() <= 0:\n            raise WorkflowInputError(\"token budget exceeded\")\n\n        key = self.journal.key(\"agent\", label, prompt, schema)\n        cached = self.journal.cached(key)\n        if cached is not MISS:\n            if schema is not None:\n                ok, err = SimpleJsonSchema(schema).validate(cached)\n                if not ok:\n                    raise WorkflowInputError(\n                        f\"cached agent output failed schema validation: {err}\"\n                    )\n            self.task.progress_event(\"workflow_agent\", label=label,\n                                     phase=phase or self._phase, status=\"cached\")\n            return cached\n\n        async with self._limits.semaphore:\n            run = await asyncio.to_thread(\n                self.runner.run, prompt, schema, label\n            )\n            result = run.value\n            tokens = run.tokens\n\n        if schema is not None:\n            ok, err = SimpleJsonSchema(schema).validate(result)\n            if not ok:\n                retry = await asyncio.to_thread(\n                    self.runner.run,","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s16_workflow_runtime/code.py#L451-L487","documentation":"On resume, agent() short-circuits with the journal's cached output, but when a schema is supplied the cached value is re-validated with SimpleJsonSchema before being returned. If validation fails, WorkflowInputError('cached agent output failed schema validation: ...') is raised, because a stale cached result that no longer matches the current schema would poison the resumed run.","triggerScenarios":"Resuming a run (resume_from_run_id) with a schema that was changed (fields added/renamed, types tightened) since the original run recorded the journal entry for that agent label/prompt/schema key.","commonSituations":"Editing a workflow's FINDINGS_SCHEMA between the original run and the resume; deploying a new schema version and resuming an old runId; hand-editing the journal file in STORE/.runtime.","solutions":["Revert the schema to the exact definition used when the original run recorded the entry, then resume again.","Start a fresh run (new runId) instead of resuming, so every agent output is regenerated against the new schema.","Delete or rename the journal for that runId in STORE so the offending cached entry is not replayed (loses all caching for that run)."],"exampleFix":"# before\nFINDINGS_SCHEMA = {\"type\": \"object\", \"required\": [\"findings\", \"summary\"]}\n# resume fails on cached entries lacking \"summary\"\n\n# after\nFINDINGS_SCHEMA = {\"type\": \"object\", \"required\": [\"findings\"]}\n# matches the schema used when the journal was written","handlingStrategy":"validation","validationCode":"from s16_workflow_runtime import SimpleJsonSchema\nok, err = SimpleJsonSchema(NEW_SCHEMA).validate(cached_entry)\nif not ok:\n    start_fresh_run()  # do not resume with a changed schema","typeGuard":"def cache_matches_schema(journal, key, schema) -> bool:\n    cached = journal.cached(key)\n    if cached is MISS:\n        return False\n    ok, _ = SimpleJsonSchema(schema).validate(cached)\n    return ok","tryCatchPattern":"try:\n    result = await workflow_call(resume_from_run_id=rid)\nexcept WorkflowInputError as e:\n    if \"cached agent output failed schema validation\" in str(e):\n        result = await workflow_call()  # fresh run, no resume\n    else:\n        raise","preventionTips":["Treat schemas as part of the journal's compatibility contract: never edit a schema while runs may be resumed.","Version workflow names (review-v2) when their schemas change, so old runIds and new code never mix.","Smoke-test a resume immediately after any schema change."],"tags":["workflow","resume","schema-validation","cache","journal"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}