{"record":{"id":"5ffd30c1ed43d5c0","repo":"ZhuLinsen/daily_stock_analysis","slug":"schema-validation-failed","errorCode":"schema_validation_failed","errorMessage":"schema_validation_failed","messagePattern":"schema_validation_failed","errorType":"error_code","errorClass":"LocalCliExtractionError","httpStatus":null,"severity":"error","filePath":"src/llm/local_cli_backend.py","lineNumber":1980,"sourceCode":"                GenerationErrorCode.INVALID_JSON,\n                \"invalid_json\",\n                details={\"error\": \"json_decoder_made_no_progress\"},\n            )\n        index = next_index\n\n        if isinstance(decoded, list):\n            for item in decoded:\n                event_index += 1\n                yield _validate_opencode_event(item, event_index=event_index)\n            continue\n\n        event_index += 1\n        yield _validate_opencode_event(decoded, event_index=event_index)\n\n\ndef _validate_opencode_event(value: Any, *, event_index: int) -> Dict[str, Any]:\n    if not isinstance(value, dict):\n        raise LocalCliExtractionError(\n            GenerationErrorCode.SCHEMA_VALIDATION_FAILED,\n            \"schema_validation_failed\",\n            details={\"event_index\": event_index, \"expected\": \"object_event\"},\n        )\n    event_type = value.get(\"type\")\n    if not isinstance(event_type, str) or not event_type.strip():\n        raise LocalCliExtractionError(\n            GenerationErrorCode.SCHEMA_VALIDATION_FAILED,\n            \"schema_validation_failed\",\n            details={\"event_index\": event_index, \"expected\": \"event_type\"},\n        )\n    return value\n\n\ndef _opencode_blocked_event_reason(event: Dict[str, Any], event_type_lower: str) -> str:\n    if (\n        event_type_lower in _OPENCODE_BLOCKED_EVENT_TYPES\n        or any(blocked in event_type_lower for blocked in _OPENCODE_BLOCKED_EVENT_TYPES)","sourceCodeStart":1962,"sourceCodeEnd":1998,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/llm/local_cli_backend.py#L1962-L1998","documentation":"A structured LocalCliExtractionError with code schema_validation_failed, raised while parsing the newline-delimited JSON event stream from the local CLI (opencode) backend. Every decoded event must be a JSON object; a non-object (string, number, list element, null) at a given event_index fails validation. It indicates the child process emitted a payload that does not conform to the expected event protocol.","triggerScenarios":"The CLI subprocess prints a bare JSON scalar or string line (e.g. \"\\\"done\\\"\" or \"42\") into stdout that is captured as an event; a list payload containing non-object items; any third-party tool, progress bar, or stray log line interleaved into the event stream that decodes to a non-object JSON value.","commonSituations":"The local CLI version changed its output protocol; another tool writes to the same stdout; debug logging accidentally routed to stdout; a wrapper script echoing JSON fragments; malformed partial lines after a truncated buffer flush.","solutions":["Reproduce the raw subprocess output (run the same CLI command manually) and inspect which line is a non-object JSON value","Pin or upgrade the local CLI to the version whose event protocol this backend expects","Ensure nothing else writes to the captured stdout of the subprocess (redirect debug logs to stderr)","If you wrap the CLI in a script, make the wrapper only emit newline-delimited JSON objects with a string 'type' field"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import json\n\ndef is_object_event(line: str) -> bool:\n    try:\n        value = json.loads(line)\n    except json.JSONDecodeError:\n        return False\n    return isinstance(value, dict)","typeGuard":"from typing import Any, Dict\n\ndef is_opencode_event(value: Any) -> \"typeguard\":\n    return isinstance(value, dict) and isinstance(value.get(\"type\"), str) and bool(value.get(\"type\").strip())","tryCatchPattern":"try:\n    for event in stream_opencode_events(proc):\n        handle(event)\nexcept LocalCliExtractionError as exc:\n    if exc.error_code == GenerationErrorCode.SCHEMA_VALIDATION_FAILED:\n        log.error(\"CLI event protocol violation: %s\", exc.details)\n        capture_raw_stream_for_diagnosis()\n    raise","preventionTips":["Pin the local CLI version so its event protocol cannot drift","Route all subprocess debug output to stderr, never the captured event stream","Keep raw stream dumps behind a debug flag so protocol violations are diagnosable"],"tags":["llm","cli","json","schema","validation"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}