{"record":{"id":"7071183a38e60866","repo":"OpenBMB/ChatDev","slug":"artifact-content-unavailable","errorCode":null,"errorMessage":"Artifact content unavailable","messagePattern":"Artifact content unavailable","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"server/routes/artifacts.py","lineNumber":85,"sourceCode":"\n@router.get(\"/api/sessions/{session_id}/artifacts/{artifact_id}\")\nasync def get_artifact(\n    session_id: str,\n    artifact_id: str,\n    mode: str = Query(\"meta\", pattern=\"^(meta|stream)$\"),\n    download: bool = Query(False),\n):\n    manager, _ = _get_session_and_queue(session_id)\n    store = manager.attachment_service.get_attachment_store(session_id)\n    record = store.get(artifact_id)\n    if not record:\n        raise HTTPException(status_code=404, detail=\"Artifact not found\")\n\n    ref = record.ref\n    if mode == \"stream\":\n        local_path = ref.local_path\n        if not local_path:\n            raise HTTPException(status_code=404, detail=\"Artifact content unavailable\")\n        path = Path(local_path)\n        if not path.exists():\n            raise HTTPException(status_code=404, detail=\"Artifact file missing\")\n        media_type = ref.mime_type or \"application/octet-stream\"\n        disposition = \"attachment\" if download else \"inline\"\n        headers = {\"Content-Disposition\": f'{disposition}; filename=\"{ref.name}\"'}\n        return StreamingResponse(path.open(\"rb\"), media_type=media_type, headers=headers)\n\n    data_uri = ref.data_uri\n    if not data_uri and ref.local_path and (ref.size or 0) <= MAX_FILE_SIZE:\n        local_path = Path(ref.local_path)\n        if local_path.exists():\n            data_uri = encode_file_to_data_uri(local_path, ref.mime_type or \"application/octet-stream\")\n    return {\n        \"artifact_id\": artifact_id,\n        \"name\": ref.name,\n        \"mime_type\": ref.mime_type,\n        \"size\": ref.size,","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/server/routes/artifacts.py#L67-L103","documentation":"The artifact record exists but its ref.local_path is None, so the server cannot stream the file content. This happens for artifacts stored inline (data URI) rather than on disk, while the request used mode=stream.","triggerScenarios":"GET .../artifacts/{id}?mode=stream for an inline/small artifact whose reference carries a data_uri instead of a local_path.","commonSituations":"Artifacts below the size threshold get inlined as data URIs; a client hardcodes mode=stream for all downloads.","solutions":["Omit mode or use the default mode so the data_uri branch is used for inline artifacts","Check the artifact event payload for whether the artifact is inline before choosing mode=stream","If streaming is required, configure the attachment store to always persist artifacts to disk"],"exampleFix":"# before\nGET /api/sessions/{sid}/artifacts/{aid}?mode=stream\n# after\nGET /api/sessions/{sid}/artifacts/{aid}  # falls back to data_uri","handlingStrategy":"fallback","validationCode":"ref = client.get_artifact_meta(session_id, artifact_id)\nmode = 'stream' if ref.get('local_path') else None","typeGuard":"def is_streamable(ref) -> bool:\n    return bool(ref.get('local_path'))","tryCatchPattern":"try:\n    data = client.get_artifact(sid, aid, mode='stream')\nexcept HTTPError as e:\n    if e.response.status_code == 404:  # content unavailable\n        data = client.get_artifact(sid, aid)  # data_uri fallback","preventionTips":["Check whether the artifact is inline before requesting stream mode","Default to no mode param for small artifacts"],"tags":["http-404","artifacts","file-storage"],"backgroundTag":"resource-unavailable","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}