{"record":{"id":"3375ceca98ac8282","repo":"janhq/jan","slug":"ingestfileattachmentforproject-attachment-is-not","errorCode":null,"errorMessage":"ingestFileAttachmentForProject: attachment is not document","messagePattern":"ingestFileAttachmentForProject: attachment is not document","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web-app/src/services/uploads/default.ts","lineNumber":34,"sourceCode":"    if (attachment.type !== 'document') throw new Error('ingestFileAttachment: attachment is not document')\n    const ext = ExtensionManager.getInstance().get<RAGExtension>(ExtensionTypeEnum.RAG)\n    if (!ext?.ingestAttachments) throw new Error('RAG extension not available')\n    const res: IngestAttachmentsResult = await ext.ingestAttachments(threadId, [\n      { path: attachment.path!, name: attachment.name, type: attachment.fileType, size: attachment.size },\n    ])\n    const files = res.files\n    if (Array.isArray(files) && files[0]?.id) {\n      return {\n        id: files[0].id,\n        size: typeof files[0].size === 'number' ? Number(files[0].size) : undefined,\n        chunkCount: typeof files[0].chunk_count === 'number' ? Number(files[0].chunk_count) : undefined,\n      }\n    }\n    throw new Error('Failed to resolve ingested attachment id')\n  }\n\n  async ingestFileAttachmentForProject(projectId: string, attachment: Attachment): Promise<UploadResult> {\n    if (attachment.type !== 'document') throw new Error('ingestFileAttachmentForProject: attachment is not document')\n    const ext = ExtensionManager.getInstance().get<RAGExtension>(ExtensionTypeEnum.RAG)\n    if (!ext?.ingestAttachmentsForProject) throw new Error('RAG extension does not support project-level ingestion')\n    const res: IngestAttachmentsResult = await ext.ingestAttachmentsForProject(projectId, [\n      { path: attachment.path!, name: attachment.name, type: attachment.fileType, size: attachment.size },\n    ])\n    const files = res.files\n    if (Array.isArray(files) && files[0]?.id) {\n      return {\n        id: files[0].id,\n        size: typeof files[0].size === 'number' ? Number(files[0].size) : undefined,\n        chunkCount: typeof files[0].chunk_count === 'number' ? Number(files[0].chunk_count) : undefined,\n      }\n    }\n    throw new Error('Failed to resolve ingested attachment id')\n  }\n}\n","sourceCodeStart":16,"sourceCodeEnd":51,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/services/uploads/default.ts#L16-L51","documentation":"ingestFileAttachmentForProject, the project-scoped variant of document ingestion, only accepts attachments whose type is exactly 'document' and throws this error for any other type. It is the same style of upfront guard as in ingestFileAttachment.","triggerScenarios":"Calling uploadsService.ingestFileAttachmentForProject(projectId, attachment) with an attachment whose type is not 'document' (e.g. 'image').","commonSituations":"A project upload flow reuses one handler for all dropped files; attachment.type was left unset or misclassified when building the Attachment object.","solutions":["Guard with attachment.type === 'document' before invoking ingestFileAttachmentForProject and route other types elsewhere","Fix attachment construction so document files are labeled type 'document'","Dispatch on attachment.type at the call site when handling mixed uploads"],"exampleFix":"// before\nawait uploads.ingestFileAttachmentForProject(projectId, att)\n// after\nif (att.type === 'document') {\n  await uploads.ingestFileAttachmentForProject(projectId, att)\n}","handlingStrategy":"type-guard","validationCode":"if (attachment.type !== 'document') { console.warn('Project upload skipped non-document', attachment.name); return }","typeGuard":"const isDocument = (a: Attachment): a is Attachment & { type: 'document' } => a.type === 'document'","tryCatchPattern":"try {\n  await uploads.ingestFileAttachmentForProject(projectId, att)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('attachment is not document')) {\n    notifyUser(`${att.name} cannot be added to a project: not a document`)\n    return\n  }\n  throw e\n}","preventionTips":["Filter dropped files to document MIME types before constructing Attachments for project upload","Share one type-dispatch helper across thread and project ingestion paths","Type the project-upload entry point to accept only document attachments"],"tags":["type-guard","uploads","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}