janhq/jan · error · Error
response.statusText
Error message
response.statusText
What it means
When importing dragged/dropped audio files via Tauri paths, the app converts the path to an asset URL and fetches it as a blob. A non-ok fetch response throws new Error(response.statusText), surfacing the HTTP failure text. The catch logs 'Failed to read audio file' and skips the file.
Solutions
- Add the needed directories to tauri.conf.json assetProtocol.scope (e.g. {"assetProtocol":{"enable":true,"scope":["**"]}}).
- Verify the file still exists and is readable before fetching.
- Check the browser console/network for the actual HTTP status to identify 403 vs 404.
- Upgrade/verify @tauri-apps/api convertFileSrc usage matches the installed Tauri version.
Example fix
// before
const response = await fetch(fileUrl)
if (!response.ok) throw new Error(response.statusText)
// after
const response = await fetch(fileUrl)
if (!response.ok) {
throw new Error(`Failed to read audio file ${path}: ${response.status} ${response.statusText}`)
} Defensive patterns
Strategy: try-catch
Validate before calling
const exists = await invoke('fs_exists', { path })
if (!exists) throw new Error(`Audio file not found: ${path}`) Type guard
const isOkResponse = (r: Response): r is Response & { ok: true } => r.ok Try / catch
try {
const response = await fetch(convertFileSrc(path))
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`)
const blob = await response.blob()
files.push(new File([blob], fileName, { type: mimeType }))
} catch (error) {
console.error('Failed to read audio file:', path, error)
toast.error(`Could not read audio: ${path.split(/[\\/]/).pop()}`)
} Prevention
- Configure assetProtocol enable/scope in tauri.conf.json to cover user file locations.
- Check file existence before fetch when paths come from async sources.
- Log response.status, not just statusText, for diagnosis.
- Show per-file user feedback when an import is skipped.
When it happens
Trigger: fetch(convertFileSrc(path)) returns 4xx/5xx — e.g. the asset protocol is not allowed for that path, the file was deleted/moved after selection, or the path is outside the Tauri asset scope.
Common situations: Dropping files from directories not whitelisted in Tauri's asset protocol scope; files on network/removable drives that vanished; Tauri security config (assetProtocol enable/scope) missing; permission errors reading the file.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Failed to fetch file
- Cannot connect to at . Please check that the service is…
- Database error
- ${e}
- Failed to decompress archive
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/e1810f2736b75485.
Report an issue: GitHub.
Appendix: source
Thrown at web-app/src/containers/ChatInput.tsx:1584
if (textareaRef.current) textareaRef.current.focus()
}
const openAudioPicker = useCallback(async () => {
if (isPlatformTauri()) {
try {
const selected = await serviceHub.dialog().open({
multiple: true,
filters: [{ name: 'Audio', extensions: ['wav', 'mp3'] }],
})
if (selected) {
const paths = Array.isArray(selected) ? selected : [selected]
const files: File[] = []
for (const path of paths) {
try {
const { convertFileSrc } = await import('@tauri-apps/api/core')
const fileUrl = convertFileSrc(path)
const response = await fetch(fileUrl)
if (!response.ok) throw new Error(response.statusText)
const blob = await response.blob()
const fileName = path.split(/[\\/]/).filter(Boolean).pop() || 'audio'
const ext = fileName.toLowerCase().split('.').pop()
const mimeType = ext === 'mp3' ? 'audio/mpeg' : 'audio/wav'
files.push(new File([blob], fileName, { type: mimeType }))
} catch (error) {
console.error('Failed to read audio file:', error)
toast.error('Failed to read audio file', {
description: error instanceof Error ? error.message : String(error),
})
}
}
if (files.length > 0) await processAudioFiles(files)
}
} catch (error) {
console.error('Failed to open audio dialog:', error)
}
if (textareaRef.current) textareaRef.current.focus()View on GitHub (pinned to 7205d770c1)