janhq/jan · error · Error

Failed to fetch file: ${response.statusText}

Error message

Failed to fetch file: ${response.statusText}

What it means

Same Tauri asset-protocol fetch pattern as the video case, but for image picking. The message includes the literal `response.statusText` so it is more debuggable than error 120, but it still surfaces an opaque custom-protocol string when the asset URL fetch is non-OK. The error is caught per-file inside the loop and shown as a toast without aborting the whole batch.

Source

Thrown at web-app/src/containers/ChatInput.tsx:1475

              extensions: ['jpg', 'jpeg', 'png'],
            },
          ],
        })

        if (selected) {
          const paths = Array.isArray(selected) ? selected : [selected]
          const files: File[] = []

          for (const path of paths) {
            try {
              // Use Tauri's convertFileSrc to create a valid URL for the file
              const { convertFileSrc } = await import('@tauri-apps/api/core')
              const fileUrl = convertFileSrc(path)

              // Fetch the file as blob
              const response = await fetch(fileUrl)
              if (!response.ok) {
                throw new Error(`Failed to fetch file: ${response.statusText}`)
              }

              const blob = await response.blob()
              const fileName =
                path.split(/[\\/]/).filter(Boolean).pop() || 'image'
              const ext = fileName.toLowerCase().split('.').pop()
              const mimeType =
                ext === 'png'
                  ? 'image/png'
                  : ext === 'jpg' || ext === 'jpeg'
                    ? 'image/jpeg'
                    : 'image/jpeg'

              const file = new File([blob], fileName, { type: mimeType })
              files.push(file)
            } catch (error) {
              console.error('Failed to read file:', error)
              toast.error('Failed to read file', {

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Confirm `security.assetProtocol.scope` covers the user's picture folders.
  2. Log `response.status` not just `statusText`, since Tauri frequently sends empty statusText.
  3. Skip the failing file and continue the batch (already partially done) but report the specific filename in the toast.
  4. Pre-check `path` validity via Tauri fs `exists()` before converting.

Example fix

// before
if (!response.ok) {
  throw new Error(`Failed to fetch file: ${response.statusText}`)
}

// after
if (!response.ok) {
  throw new Error(
    `Failed to fetch file ${fileName}: HTTP ${response.status}${
      response.statusText ? ` ${response.statusText}` : ''
    }`
  )
}
Defensive patterns

Strategy: try-catch

Validate before calling

const { exists } = await import('@tauri-apps/plugin-fs')
if (!(await exists(path))) {
  toast.error('Image file no longer exists', { description: path })
  continue
}

Type guard

function isReadableImageResponse(res: Response): res is Response & { ok: true } {
  return res.ok && (res.headers.get('content-type')?.startsWith('image/') ?? true)
}

Try / catch

try {
  const response = await fetch(fileUrl)
  if (!response.ok) {
    toast.error('Could not read image', {
      description: `HTTP ${response.status} for ${fileName}`,
    })
    continue
  }
  // ... build File
} catch (error) {
  toast.error('Failed to read file', {
    description: error instanceof Error ? error.message : String(error),
  })
}

Prevention

When it happens

Trigger: Picking one or more images via `serviceHub.dialog().open({ filters: [{ name: 'Images', extensions: ['jpg','jpeg','png'] }] })`, then `fetch(convertFileSrc(path))` returning non-OK. Same triggers as 120: scope mismatch, deleted file, permission, or a non-image path slipping through the filter.

Common situations: Asset scope missing the picked directory; symlink/junction paths not covered by scope globs; the user picked a file whose extension matched but content is unreadable; cross-platform path normalization (forward vs back slashes) producing a bad asset URL.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/1aeeb18962faf8ca. Report an issue: GitHub.