{"record":{"id":"3443313a66f0dcd7","repo":"can1357/oh-my-pi","slug":"field-must-be-a-string","errorCode":null,"errorMessage":"{field} must be a string","messagePattern":"(.+?) must be a string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/omp-rpc/src/omp_rpc/protocol.py","lineNumber":206,"sourceCode":"def _require_literal(value: object, allowed: frozenset[str], *, field: str) -> str:\n    if not isinstance(value, str) or value not in allowed:\n        expected = \", \".join(sorted(allowed))\n        raise ValueError(f\"{field} must be one of: {expected}\")\n    return value\n\n\ndef _optional_literal(\n    value: object, allowed: frozenset[str], *, field: str\n) -> str | None:\n    if value is None:\n        return None\n    return _require_literal(value, allowed, field=field)\n\n\ndef _require_str(payload: JsonObject, field: str) -> str:\n    value = payload.get(field)\n    if not isinstance(value, str):\n        raise ValueError(f\"{field} must be a string\")\n    return value\n\n\ndef _require_bool(payload: JsonObject, field: str) -> bool:\n    value = payload.get(field)\n    if not isinstance(value, bool):\n        raise ValueError(f\"{field} must be a boolean\")\n    return value\n\n\ndef _optional_str(payload: JsonObject, field: str) -> str | None:\n    value = payload.get(field)\n    if value is None:\n        return None\n    if not isinstance(value, str):\n        raise ValueError(f\"{field} must be a string\")\n    return value\n","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/omp-rpc/src/omp_rpc/protocol.py#L188-L224","documentation":"omp-rpc's protocol parser validates every field of an incoming JSON payload before constructing typed objects. `_require_str` throws this ValueError when a required field named `{field}` is missing or is not a JSON string. The library fails fast so malformed payloads surface at parse time instead of causing type errors deep in application code.","triggerScenarios":"Calling parse_model_info, parse_tool_descriptor, parse_todo_item, parse_todo_phase, parse_session_state, or _parse_thinking_config with a payload whose required field is absent (None), a number, bool, list, or dict instead of a string — e.g. a deserialized RPC response missing `id` or carrying `id: 123` instead of `\"123\"`.","commonSituations":"A server upgraded and renamed/retyped a field; a hand-built fixture or mock response uses a numeric ID; JSON was produced by a non-Python serializer that emits unquoted values; a partially-constructed dict was passed to the parser.","solutions":["Log/print the full payload and check the named field's actual JSON type before calling the parser","Coerce or fix the value to a string (str(value) or correct the producer)","If the field is legitimately absent, use the optional variant or supply a default before parsing","Pin both client and server to compatible omp-rpc versions so the wire schema matches"],"exampleFix":"# before\npayload = {\"id\": 42, \"name\": \"bash\"}\ninfo = parse_tool_descriptor(payload)  # ValueError: id must be a string\n# after\npayload = {\"id\": str(42), \"name\": \"bash\"}\ninfo = parse_tool_descriptor(payload)","handlingStrategy":"validation","validationCode":"def ensure_str(payload: dict, field: str) -> None:\n    value = payload.get(field)\n    if not isinstance(value, str):\n        raise TypeError(f\"{field!r} must be a string, got {type(value).__name__}: {value!r}\")\n\n# before parsing:\nensure_str(payload, \"id\")\nparse_tool_descriptor(payload)","typeGuard":"def is_str_field(payload: dict, field: str) -> bool:\n    return isinstance(payload.get(field), str)","tryCatchPattern":"try:\n    info = parse_tool_descriptor(payload)\nexcept ValueError as e:\n    logger.error(\"invalid tool descriptor payload\", extra={\"payload\": payload, \"error\": str(e)})\n    raise ProtocolError(\"malformed tool descriptor\") from e","preventionTips":["Validate payloads against the protocol schema at the boundary before parsing","Keep client and omp-rpc versions in lockstep with the server","Never hand-build IDs or names as numbers; stringify at production time","Log the raw payload on parse failure to speed diagnosis"],"tags":["python","rpc","type-validation","payload-parsing"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}