{"record":{"id":"f305452c7813402d","repo":"can1357/oh-my-pi","slug":"hosturireadresult-requires-a-content-field","errorCode":null,"errorMessage":"HostUriReadResult requires a 'content' field","messagePattern":"HostUriReadResult requires a 'content' field","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/omp-rpc/src/omp_rpc/host_uris.py","lineNumber":110,"sourceCode":"    )\n\n\ndef normalize_read_result(value: HostUriReadValue) -> JsonObject:\n    \"\"\"Convert a handler's `read` return into the wire-frame fields.\n\n    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":92,"sourceCodeEnd":127,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/omp-rpc/src/omp_rpc/host_uris.py#L92-L127","documentation":"When normalize_read_result() receives a dict from a read handler, that dict must include a 'content' key — it is the only field the host_uri_result payload requires. A dict without 'content' (e.g. only 'notes' or 'content_type') raises ValueError. String returns are exempt because they are auto-wrapped into {'content': ...}.","triggerScenarios":"Returning a dict like {'notes': ['empty'], 'content_type': 'text/plain'} from a read handler and forgetting 'content'; building the result dict conditionally so 'content' is omitted on an empty/error branch; passing an already-parsed JSON object that uses a different key name like 'text' or 'body'.","commonSituations":"Handlers that return metadata-only dicts for edge cases (missing file, empty resource), key renamed during a refactor ('text' -> 'content'), or spreading a config dict that happens to lack 'content'.","solutions":["Always include 'content' in the returned dict: {'content': str(value), ...} even when it is an empty string or an explanatory message","If there is nothing to return, return a string like 'resource not found' instead of a bare dict","Rename alternate keys ('text', 'body', 'data') to 'content' in the handler"],"exampleFix":"// before\ndef read(path):\n    if not exists(path):\n        return {'notes': ['missing']}\n// after\ndef read(path):\n    if not exists(path):\n        return {'content': '', 'notes': ['resource not found']}\n","handlingStrategy":"type-guard","validationCode":"def check_read_dict(value: dict) -> dict:\n    if 'content' not in value:\n        raise ValueError(\"read result dict requires a 'content' field\")\n    return value","typeGuard":"def has_content(value) -> bool:\n    return isinstance(value, dict) and 'content' in value","tryCatchPattern":"try:\n    payload = normalize_read_result(handler_result)\nexcept (TypeError, ValueError) as e:\n    logger.error('invalid read result: %s', e)\n    payload = {'content': ''}","preventionTips":["Adopt a helper that builds read results and always sets 'content', even to ''","Never return metadata-only dicts from handlers; fold diagnostics into 'notes' alongside a non-empty 'content'","Standardize on the key 'content' — do not alias to 'text'/'body' in handlers"],"tags":["valueerror","host-uri","read-handler","missing-field"],"backgroundTag":"missing-required-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}