janhq/jan · error

ingestImage: attachment is not image

Error message

ingestImage: attachment is not image

What it means

DefaultUploadsService.ingestImage is a single-purpose method that only accepts attachments whose type is exactly 'image'. It throws this error immediately when handed an Attachment with any other type (e.g. 'document'). The check is a guard in front of a placeholder upload flow that returns a generated ulid.

Solutions

  1. Check attachment.type === 'image' before calling ingestImage and route non-image attachments to ingestFileAttachment instead
  2. Fix the code that constructs the Attachment so image files get type 'image'
  3. If the call site legitimately receives mixed attachments, branch on type rather than calling ingestImage unconditionally

Example fix

// before
const result = await uploads.ingestImage(threadId, attachment)
// after
const result = attachment.type === 'image'
  ? await uploads.ingestImage(threadId, attachment)
  : await uploads.ingestFileAttachment(threadId, attachment)
Defensive patterns

Strategy: type-guard

Validate before calling

if (attachment.type !== 'image') { console.warn('Skipping non-image attachment', attachment.name); return }

Type guard

const isImageAttachment = (a: Attachment): a is Attachment & { type: 'image' } => a.type === 'image'

Try / catch

try {
  const result = await uploads.ingestImage(threadId, att)
} catch (e) {
  if (e instanceof Error && e.message.includes('attachment is not image')) {
    return uploads.ingestFileAttachment(threadId, att)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling uploadsService.ingestImage(threadId, attachment) with an attachment whose attachment.type is not 'image' — e.g. passing a document/PDF attachment or an attachment whose type was never set during file selection.

Common situations: A caller routes all attachments to ingestImage without inspecting type first; a file picker produces attachments with type inferred incorrectly; a refactor changed the Attachment type union and the caller's mapping was not updated.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/8cfd9d16c7174e74. Report an issue: GitHub.

Appendix: source

Thrown at web-app/src/services/uploads/default.ts:9

import type { UploadsService, UploadResult } from './types'
import type { Attachment } from '@/types/attachment'
import { ulid } from 'ulidx'
import { ExtensionManager } from '@/lib/extension'
import { ExtensionTypeEnum, type RAGExtension, type IngestAttachmentsResult } from '@janhq/core'

export class DefaultUploadsService implements UploadsService {
  async ingestImage(_threadId: string, attachment: Attachment): Promise<UploadResult> {
    if (attachment.type !== 'image') throw new Error('ingestImage: attachment is not image')
    // Placeholder upload flow; swap for real API call when backend is ready
    await new Promise((r) => setTimeout(r, 100))
    return { id: ulid() }
  }

  async ingestFileAttachment(threadId: string, attachment: Attachment): Promise<UploadResult> {
    if (attachment.type !== 'document') throw new Error('ingestFileAttachment: attachment is not document')
    const ext = ExtensionManager.getInstance().get<RAGExtension>(ExtensionTypeEnum.RAG)
    if (!ext?.ingestAttachments) throw new Error('RAG extension not available')
    const res: IngestAttachmentsResult = await ext.ingestAttachments(threadId, [
      { path: attachment.path!, name: attachment.name, type: attachment.fileType, size: attachment.size },
    ])
    const files = res.files
    if (Array.isArray(files) && files[0]?.id) {
      return {
        id: files[0].id,
        size: typeof files[0].size === 'number' ? Number(files[0].size) : undefined,
        chunkCount: typeof files[0].chunk_count === 'number' ? Number(files[0].chunk_count) : undefined,

View on GitHub (pinned to 7205d770c1)