{"record":{"id":"73db11baca29eb59","repo":"can1357/oh-my-pi","slug":"unsupported-content-type-content-type-r","errorCode":null,"errorMessage":"Unsupported content_type: {content_type!r}","messagePattern":"Unsupported content_type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/omp-rpc/src/omp_rpc/host_uris.py","lineNumber":116,"sourceCode":"    Returns a dict suitable for spreading into a `host_uri_result` payload.\n    \"\"\"\n\n    if isinstance(value, str):\n        return {\"content\": value}\n    if not isinstance(value, dict):\n        raise TypeError(\n            \"Host URI read handlers must return a string or a HostUriReadResult mapping\"\n        )\n\n    payload: JsonObject = {}\n    if \"content\" not in value:\n        raise ValueError(\"HostUriReadResult requires a 'content' field\")\n    payload[\"content\"] = str(value[\"content\"])\n\n    content_type = value.get(\"content_type\")\n    if content_type is not None:\n        if content_type not in (\"text/markdown\", \"application/json\", \"text/plain\"):\n            raise ValueError(f\"Unsupported content_type: {content_type!r}\")\n        payload[\"contentType\"] = content_type\n\n    notes = value.get(\"notes\")\n    if notes is not None:\n        payload[\"notes\"] = [str(item) for item in notes]\n\n    if \"immutable\" in value:\n        payload[\"immutable\"] = bool(value[\"immutable\"])\n\n    return payload\n","sourceCodeStart":98,"sourceCodeEnd":127,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/omp-rpc/src/omp_rpc/host_uris.py#L98-L127","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before\nreturn {'content': json.dumps(data), 'content_type': 'text/html'}\n// after\nreturn {'content': json.dumps(data), 'content_type': 'application/json'}","handlingStrategy":"validation","validationCode":"ALLOWED = ('text/markdown', 'application/json', 'text/plain')\ndef check_content_type(ct):\n    if ct is not None and ct not in ALLOWED:\n        raise ValueError(f'content_type must be one of {ALLOWED}, got {ct!r}')\n    return ct","typeGuard":"def is_allowed_content_type(ct) -> bool:\n    return ct is None or ct in ('text/markdown', 'application/json', 'text/plain')","tryCatchPattern":"try:\n    payload = normalize_read_result(result)\nexcept ValueError as e:\n    if 'content_type' in str(e):\n        payload = normalize_read_result({**result, 'content_type': 'text/plain'})\n    else:\n        raise","preventionTips":["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"],"tags":["valueerror","host-uri","content-type","validation"],"backgroundTag":"unsupported-content-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}