can1357/oh-my-pi · error · ValueError
Unsupported content_type: {content_type!r}
Error message
Unsupported content_type: {content_type!r} What it means
normalize_read_result() validates the optional 'content_type' field of a read-result dict against an allowlist: 'text/markdown', 'application/json', 'text/plain'. Any other MIME type (or a malformed value) raises ValueError, because the host only knows how to render/interpret these three content types. Set content_type to None (or omit it) to use the default.
Source
Thrown at python/omp-rpc/src/omp_rpc/host_uris.py:116
Returns a dict suitable for spreading into a `host_uri_result` payload.
"""
if isinstance(value, str):
return {"content": value}
if not isinstance(value, dict):
raise TypeError(
"Host URI read handlers must return a string or a HostUriReadResult mapping"
)
payload: JsonObject = {}
if "content" not in value:
raise ValueError("HostUriReadResult requires a 'content' field")
payload["content"] = str(value["content"])
content_type = value.get("content_type")
if content_type is not None:
if content_type not in ("text/markdown", "application/json", "text/plain"):
raise ValueError(f"Unsupported content_type: {content_type!r}")
payload["contentType"] = content_type
notes = value.get("notes")
if notes is not None:
payload["notes"] = [str(item) for item in notes]
if "immutable" in value:
payload["immutable"] = bool(value["immutable"])
return payload
View on GitHub (pinned to 9690622007)
Solutions
- Use one of the three allowed values exactly: 'text/markdown', 'application/json', or 'text/plain'
- Strip MIME parameters: 'text/plain; charset=utf-8'.split(';')[0].strip()
- Omit 'content_type' entirely (default) or serialize unsupported data to JSON/text before returning
Example fix
// before
return {'content': json.dumps(data), 'content_type': 'text/html'}
// after
return {'content': json.dumps(data), 'content_type': 'application/json'} Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = ('text/markdown', 'application/json', 'text/plain')
def check_content_type(ct):
if ct is not None and ct not in ALLOWED:
raise ValueError(f'content_type must be one of {ALLOWED}, got {ct!r}')
return ct Type guard
def is_allowed_content_type(ct) -> bool:
return ct is None or ct in ('text/markdown', 'application/json', 'text/plain') Try / catch
try:
payload = normalize_read_result(result)
except ValueError as e:
if 'content_type' in str(e):
payload = normalize_read_result({**result, 'content_type': 'text/plain'})
else:
raise Prevention
- Strip MIME parameters (charset/boundary) before assigning content_type
- Serialize unsupported formats to JSON or text instead of declaring their raw MIME type
- Keep a shared constant list of allowed types in your codebase and validate against it
- Re-check handlers after upgrading the library in case the allowlist changed
When it happens
Trigger: Returning {'content': '...', 'content_type': 'text/html'} or 'application/octet-stream' from a read handler; passing 'text/markdown; charset=utf-8' (with parameters) which fails exact membership; typos like 'text/md' or 'plain/text'.
Common situations: Handler echoing the source file's MIME type (images, CSV, HTML) instead of converting to an allowed type; charset suffix appended by a generic MIME-detection helper; drift after the library tightened the allowlist and old handlers still emit legacy types.
Related errors
- scheme must be a non-empty string
- Failed to load tree-sitter language: {err}
- Host URI scheme must be a non-empty string
- Host URI scheme contains invalid characters: ${raw.scheme}
- Host URI scheme is reserved by OMP: ${scheme}://
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/73db11baca29eb59.
Report an issue: GitHub.