{"record":{"id":"5ebce1326fddc237","repo":"janhq/jan","slug":"no-id-returned-from-image-ingestion","errorCode":null,"errorMessage":"No ID returned from image ingestion","messagePattern":"No ID returned from image ingestion","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/containers/ChatInput.tsx","lineNumber":1091,"sourceCode":"              const result = await serviceHub\n                .uploads()\n                .ingestImage(currentThreadId, img)\n\n              if (result?.id) {\n                setAttachmentsForThread(attachmentsKey, (prev) =>\n                  prev.map((a) =>\n                    matchImg(a)\n                      ? {\n                          ...a,\n                          processing: false,\n                          processed: true,\n                          id: result.id,\n                        }\n                      : a\n                  )\n                )\n              } else {\n                throw new Error('No ID returned from image ingestion')\n              }\n            } catch (error) {\n              console.error('Failed to ingest image:', error)\n              setAttachmentsForThread(attachmentsKey, (prev) =>\n                prev.filter((a) => !matchImg(a))\n              )\n              toast.error(`Failed to ingest ${img.name}`, {\n                description:\n                  error instanceof Error ? error.message : String(error),\n              })\n            } finally {\n              setFileIngestProgress({\n                completed: i + 1,\n                total: ingestTotal,\n              })\n            }\n          }\n        } finally {","sourceCodeStart":1073,"sourceCodeEnd":1109,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/containers/ChatInput.tsx#L1073-L1109","documentation":"This error is thrown in the React frontend when serviceHub.uploads().ingestImage() resolves successfully but the returned object has no id property (or id is falsy). The image ingestion pipeline is expected to return an object with an id field representing the stored vector/embedding. A missing id means the backend accepted the request but did not return a valid identifier, making the attachment unusable for retrieval.","triggerScenarios":"The vector-db plugin's ingestImage command returns an empty or null result object. The backend stored the image but failed to return the generated ID (serialization issue). A race condition where the result is partially constructed. The backend returned a different response shape than expected (e.g. { uuid } instead of { id }).","commonSituations":"Vector database not initialized when ingestion is attempted. Plugin version mismatch changing the response contract. Backend returning { ok: true } without an id. SQLite insert succeeded but last_insert_rowid() returned 0. Network/IPC serialization dropping the id field.","solutions":["Verify the vector-db plugin is initialized and healthy before ingesting images.","Check the backend ingestImage command's return type matches { id: string }.","Log the full result object to inspect the actual response shape.","Ensure the SQLite/vector store has the correct schema for image embeddings."],"exampleFix":"// before\nconst result = await serviceHub.uploads().ingestImage(currentThreadId, img)\nif (result?.id) { /* use result.id */ }\nelse { throw new Error('No ID returned from image ingestion') }\n\n// after\nconst result = await serviceHub.uploads().ingestImage(currentThreadId, img)\nconst id = result?.id ?? result?.uuid ?? result?._id\nif (!id) {\n  console.error('Unexpected ingest result shape:', JSON.stringify(result))\n  throw new Error(`No ID returned from image ingestion: ${JSON.stringify(result)}`)\n}","handlingStrategy":"type-guard","validationCode":"// Before using the result, validate its shape\ninterface IngestResult { id: string }\n\nfunction isIngestResult(v: unknown): v is IngestResult {\n  return typeof v === 'object' && v !== null &&\n    typeof (v as Record<string, unknown>).id === 'string' &&\n    (v as Record<string, unknown>).id!.length > 0;\n}\n\nconst result = await serviceHub.uploads().ingestImage(currentThreadId, img);\nif (!isIngestResult(result)) {\n  console.error('Unexpected ingest result:', JSON.stringify(result));\n  throw new Error(`No ID returned from image ingestion: ${JSON.stringify(result)}`);\n}","typeGuard":"function hasValidId(v: unknown): v is { id: string } {\n  return typeof v === 'object' && v !== null &&\n    typeof (v as Record<string, unknown>).id === 'string' &&\n    ((v as Record<string, unknown>).id as string).length > 0;\n}","tryCatchPattern":"try {\n  const result = await serviceHub.uploads().ingestImage(currentThreadId, img);\n  if (!result?.id) {\n    throw new Error(`No ID returned: ${JSON.stringify(result)}`);\n  }\n  // use result.id\n} catch (error) {\n  setAttachmentsForThread(attachmentsKey, (prev) => prev.filter((a) => !matchImg(a)));\n  toast.error(`Failed to ingest ${img.name}`, {\n    description: error instanceof Error ? error.message : String(error),\n  });\n}","preventionTips":["Type-guard the ingest result before accessing .id.","Log the full result object when the id is missing to diagnose backend issues.","Verify the vector-db plugin is initialized before allowing image uploads.","Coordinate the response contract between frontend and backend in a shared type."],"tags":["typescript","react","image-ingestion","vector-db","frontend","ipc"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}