can1357/oh-my-pi · error · ValueError
{field} must be an integer
Error message
{field} must be an integer What it means
`_optional_int` accepts absence but otherwise demands a JSON integer; it explicitly rejects booleans (checked first because bool subclasses int in Python) and rejects floats and strings. This keeps counts/indices/ids strictly integral.
Source
Thrown at python/omp-rpc/src/omp_rpc/protocol.py:263
return tuple(items)
raise ValueError(f"{field} must be a string or an array of strings")
def _optional_bool(payload: JsonObject, field: str) -> bool | None:
value = payload.get(field)
if value is None:
return None
if not isinstance(value, bool):
raise ValueError(f"{field} must be a boolean")
return value
def _optional_int(payload: JsonObject, field: str) -> int | None:
value = payload.get(field)
if value is None:
return None
if isinstance(value, bool) or not isinstance(value, int):
raise ValueError(f"{field} must be an integer")
return value
def _optional_float(payload: JsonObject, field: str) -> float | None:
value = payload.get(field)
if value is None:
return None
if isinstance(value, bool) or not isinstance(value, (int, float)):
raise ValueError(f"{field} must be a number")
return float(value)
def _tuple_of_strings(values: object, *, field: str) -> tuple[str, ...] | None:
if values is None:
return None
if not isinstance(values, list):
raise ValueError(f"{field} must be a list")
View on GitHub (pinned to 9690622007)
Solutions
- Coerce to int before parsing: int(float(value)) for floats, int(value) for numeric strings
- Fix the producer to emit JSON integers without decimal points
- Verify the key holds the intended field — a swapped key often explains a type surprise
Example fix
# before
payload = {"exit_code": "0"}
result = parse_bash_result(payload) # ValueError: exit_code must be an integer
# after
payload = {"exit_code": int("0")}
result = parse_bash_result(payload) Defensive patterns
Strategy: validation
Validate before calling
def coerce_optional_int(payload: dict, field: str) -> dict:
value = payload.get(field)
if value is not None and not isinstance(value, bool):
if isinstance(value, float) and value.is_integer():
payload[field] = int(value)
elif isinstance(value, str) and value.lstrip("-").isdigit():
payload[field] = int(value)
if payload.get(field) is not None and not isinstance(payload[field], int):
raise TypeError(f"{field!r} must be an integer, got {value!r}")
return payload
parse_bash_result(coerce_optional_int(payload, "exit_code")) Type guard
def is_optional_int(payload: dict, field: str) -> bool:
value = payload.get(field)
return value is None or (isinstance(value, int) and not isinstance(value, bool)) Try / catch
try:
result = parse_bash_result(payload)
except ValueError as e:
logger.warning("bash result had non-integer numeric field", extra={"error": str(e)})
result = None Prevention
- Ensure serializers emit whole numbers without decimal points (JS numbers via JSON can become floats)
- Never route integers through string formatting (shell, CSV) before sending
- Explicitly exclude bools from int fields — check isinstance(value, bool) first
- Capture and diff real payloads when upgrading the server
When it happens
Trigger: parse_assistant_message_event, parse_bash_result, parse_extension_ui_request, or parse_notification receives a field like an exit code, token count, or message index as a float (3.0), a numeric string ("42"), or true/false.
Common situations: A producer serializes integers as floats (JavaScript numbers can arrive as 3.0 via some serializers); values passed through shell/CSV round-trips become strings; a boolean flag was put in an int field.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- {field} must be a string
- {field} must be a boolean
- {field}[{index}] must be a string
- {field} must be a string or an array of strings
- {field} must be a number
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c60ba7f6546f85c8.
Report an issue: GitHub.