{"record":{"id":"7de280cfc46ca714","repo":"can1357/oh-my-pi","slug":"assistantmessageevent-delta-must-be-a-string","errorCode":null,"errorMessage":"assistantMessageEvent.delta must be a string","messagePattern":"assistantMessageEvent\\.delta must be a string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/omp-rpc/src/omp_rpc/protocol.py","lineNumber":377,"sourceCode":"            return AssistantThinkingStartEvent(\n                type=\"thinking_start\", contentIndex=content_index, partial=partial\n            )\n        return AssistantToolCallStartEvent(\n            type=\"toolcall_start\", contentIndex=content_index, partial=partial\n        )\n    if event_type in {\"text_delta\", \"thinking_delta\", \"toolcall_delta\"}:\n        partial = _parse_assistant_message(\n            _clone_json_object(\n                payload.get(\"partial\"), field=\"assistantMessageEvent.partial\"\n            ),\n            field=\"assistantMessageEvent.partial\",\n        )\n        content_index = _optional_int(payload, \"contentIndex\")\n        delta = _optional_str(payload, \"delta\")\n        if content_index is None:\n            raise ValueError(\"assistantMessageEvent.contentIndex must be an integer\")\n        if delta is None:\n            raise ValueError(\"assistantMessageEvent.delta must be a string\")\n        if event_type == \"text_delta\":\n            return AssistantTextDeltaEvent(\n                type=\"text_delta\",\n                contentIndex=content_index,\n                delta=delta,\n                partial=partial,\n            )\n        if event_type == \"thinking_delta\":\n            return AssistantThinkingDeltaEvent(\n                type=\"thinking_delta\",\n                contentIndex=content_index,\n                delta=delta,\n                partial=partial,\n            )\n        return AssistantToolCallDeltaEvent(\n            type=\"toolcall_delta\",\n            contentIndex=content_index,\n            delta=delta,","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/omp-rpc/src/omp_rpc/protocol.py#L359-L395","documentation":"Delta events require a 'delta' string holding the incremental text/thinking/tool-call fragment. This error is raised when the delta key is absent or not a string (numbers, objects, null are rejected). It guarantees typed delta events always carry string content.","triggerScenarios":"text_delta/thinking_delta/toolcall_delta notification missing 'delta', or with delta as an object/array/number; an emitter sending full content instead of the incremental fragment in a non-string form.","commonSituations":"Translating provider SDK events where the fragment field has a different name (e.g. 'text'); sending null deltas for empty chunks; JSON encoding fragments as token arrays.","solutions":["Ensure delta is always a JSON string, using \"\" for empty fragments","Fix the mapping from provider event field names to the protocol's 'delta' key","Reject malformed chunks at the translation layer before parsing","Upgrade mismatched protocol versions"],"exampleFix":"// before\n{\"type\": \"text_delta\", \"contentIndex\": 0, \"delta\": null}\n// after\n{\"type\": \"text_delta\", \"contentIndex\": 0, \"delta\": \"\"}","handlingStrategy":"validation","validationCode":"if event.get(\"type\") in {\"text_delta\", \"thinking_delta\", \"toolcall_delta\"} and not isinstance(event.get(\"delta\"), str):\n    raise ValueError(\"delta event missing string delta\")","typeGuard":"def has_string_delta(e: dict) -> bool:\n    return isinstance(e.get(\"delta\"), str)","tryCatchPattern":"try:\n    event = parse_assistant_message_event(chunk)\nexcept ValueError as e:\n    logger.warning(\"skipping delta without string fragment: %s\", e)\n    event = None","preventionTips":["Map provider fragment fields explicitly to 'delta' as a string","Use \"\" for empty fragments instead of null","Sanitize third-party events before parsing"],"tags":["protocol","validation","streaming"],"backgroundTag":"missing-required-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}