janhq/jan · error · Error
Failed to ingest file
Error message
Failed to ingest file
What it means
Thrown by the project-uploads zustand store during its ingest loop when ingestFn(projectId, att) resolved but result.id is falsy. It stops the batch and reports the failing file via handlers.onError(error, currentFileName). It is the store-level wrapper over upstream upload-service failures (e.g., cascading from errors 172/173).
Source
Thrown at web-app/src/stores/project-uploads-store.ts:77
currentFileName = att.name
set((s) => {
const existing = s.progress[projectId]
if (!existing) return s
return {
progress: {
...s.progress,
[projectId]: {
...existing,
current: i,
currentFileName: att.name,
},
},
}
})
const result = await ingestFn(projectId, att)
if (!result.id) throw new Error('Failed to ingest file')
set((s) => {
const existing = s.progress[projectId]
const nextTick = (s.completedTick[projectId] ?? 0) + 1
return {
progress: existing
? {
...s.progress,
[projectId]: { ...existing, current: i + 1 },
}
: s.progress,
completedTick: { ...s.completedTick, [projectId]: nextTick },
}
})
}
handlers.onSuccess()
} catch (error) {
handlers.onError(error, currentFileName)View on GitHub (pinned to fad3f12a14)
Solutions
- Inspect the underlying ingestFn - usually ingestFileAttachmentForProject - for why no id came back (see errors 172/173).
- Check the RAG backend logs for the specific file named in onError.
- Validate file type/size before adding files to the batch.
Example fix
// before: a single missing id aborts the whole batch
const result = await ingestFn(projectId, att)
if (!result.id) throw new Error('Failed to ingest file')
// after: collect per-file failures and continue
const result = await ingestFn(projectId, att)
if (!result.id) { failed.push(att.name); continue } Defensive patterns
Strategy: try-catch
Validate before calling
function hasIngestId(r: { id?: string } | null | undefined): boolean { return !!r?.id } Type guard
function isIngestSuccess(r: unknown): r is { id: string } {
return typeof (r as any)?.id === 'string' && !!((r as any).id)
} Try / catch
await useProjectUploads.getState().ingest(pid, attachments, ingestFn, {
onSuccess: () => refreshFiles(pid),
onError: (e, fileName) => toast.error(`Failed to ingest ${fileName ?? 'file'}`),
}) Prevention
- Provide a clear onError that names the failing file.
- Consider per-file failure collection instead of aborting the whole batch.
- Pre-validate attachments before starting the batch.
When it happens
Trigger: For some attachment in the batch, ingestFn returned a result whose id is undefined/null/empty-string. The store throws 'Failed to ingest file', which is caught by the surrounding try and routed to handlers.onError with the current file name.
Common situations: Underlying upload service (DefaultUploadsService.ingestFileAttachmentForProject) returned no id; project RAG backend silently rejected the file; integration returned a malformed result object.
Related errors
- ingestFileAttachmentForProject: attachment is not document
- RAG extension does not support project-level ingestion
- Vector DB extension does not support project-level ingestion
- File '${f.name}' exceeds size limit (${f.size} bytes > ${max
- File '${file.name}' has already been attached to this projec
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/e99a1610842ff150.
Report an issue: GitHub.