{"record":{"id":"e1810f2736b75485","repo":"janhq/jan","slug":"response-statustext","errorCode":null,"errorMessage":"response.statusText","messagePattern":"response\\.statusText","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/containers/ChatInput.tsx","lineNumber":1291,"sourceCode":"    if (textareaRef.current) textareaRef.current.focus()\n  }\n\n  const openAudioPicker = useCallback(async () => {\n    if (isPlatformTauri()) {\n      try {\n        const selected = await serviceHub.dialog().open({\n          multiple: true,\n          filters: [{ name: 'Audio', extensions: ['wav', 'mp3'] }],\n        })\n        if (selected) {\n          const paths = Array.isArray(selected) ? selected : [selected]\n          const files: File[] = []\n          for (const path of paths) {\n            try {\n              const { convertFileSrc } = await import('@tauri-apps/api/core')\n              const fileUrl = convertFileSrc(path)\n              const response = await fetch(fileUrl)\n              if (!response.ok) throw new Error(response.statusText)\n              const blob = await response.blob()\n              const fileName = path.split(/[\\\\/]/).filter(Boolean).pop() || 'audio'\n              const ext = fileName.toLowerCase().split('.').pop()\n              const mimeType = ext === 'mp3' ? 'audio/mpeg' : 'audio/wav'\n              files.push(new File([blob], fileName, { type: mimeType }))\n            } catch (error) {\n              console.error('Failed to read audio file:', error)\n              toast.error('Failed to read audio file', {\n                description: error instanceof Error ? error.message : String(error),\n              })\n            }\n          }\n          if (files.length > 0) await processAudioFiles(files)\n        }\n      } catch (error) {\n        console.error('Failed to open audio dialog:', error)\n      }\n      if (textareaRef.current) textareaRef.current.focus()","sourceCodeStart":1273,"sourceCodeEnd":1309,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/containers/ChatInput.tsx#L1273-L1309","documentation":"This error is thrown when fetching an audio file via the Tauri convertFileSrc protocol returns a non-ok HTTP response. convertFileSrc converts a local filesystem path to a tauri:// or http://localhost URL that the webview can fetch. A non-ok response means the Tauri asset protocol handler could not serve the file. The error message is response.statusText, which may be empty under HTTP/2 (no statusText) or when the webview returns a bare status code.","triggerScenarios":"The selected file path no longer exists (deleted between dialog selection and fetch). File permissions deny read access. The path contains characters that break the Tauri asset protocol URL encoding. The file is on a different mount or removable media that was ejected. The webview's asset protocol scope does not include the file's directory.","commonSituations":"User selects a file from a USB drive that was disconnected before the fetch runs. File path with Unicode characters or spaces causing URL encoding issues. Tauri security config (tauri.conf.json security.csp or assetProtocol.scope) restricting access to certain directories. Permission denied on macOS due to App Sandbox without entitlements.","solutions":["Verify the file exists and is readable before calling fetch: use fs.exists via Tauri API.","Expand the asset protocol scope in tauri.conf.json security.assetProtocol.scope.","Handle empty statusText by including the status code in the error message.","On macOS, ensure the app has the necessary file access entitlements."],"exampleFix":"// before\nconst response = await fetch(fileUrl)\nif (!response.ok) throw new Error(response.statusText)\n\n// after\nconst response = await fetch(fileUrl)\nif (!response.ok) {\n  throw new Error(`HTTP ${response.status}: ${response.statusText || 'failed to load audio file'}`)\n}","handlingStrategy":"validation","validationCode":"// Before fetching, verify the file exists via Tauri fs API\nimport { exists } from '@tauri-apps/plugin-fs';\n\nif (!(await exists(path))) {\n  toast.error('File not found', { description: path });\n  continue;\n}\n\n// Or check readability:\ntry {\n  const stat = await statFile(path);\n  if (!stat.isFile) { throw new Error('Not a regular file'); }\n} catch { toast.error('Cannot access file'); continue; }","typeGuard":null,"tryCatchPattern":"const response = await fetch(fileUrl);\nif (!response.ok) {\n  throw new Error(\n    `HTTP ${response.status}: ${response.statusText || 'failed to load audio file'}`\n  );\n}\n// Also catch network-level fetch failures:\ntry {\n  const blob = await response.blob();\n} catch (e) {\n  throw new Error(`Failed to read audio data: ${e instanceof Error ? e.message : e}`);\n}","preventionTips":["Verify the file exists before fetching it via the asset protocol.","Expand the assetProtocol.scope in tauri.conf.json to include accessible directories.","Include the HTTP status code in the error message (statusText may be empty under HTTP/2).","On macOS, ensure the app has file access entitlements for user-selected files."],"tags":["typescript","tauri","asset-protocol","fetch","audio","file-access"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}