{"record":{"id":"2ea721157296a83a","repo":"mastra-ai/mastra","slug":"failed-to-get-file-content-type","errorCode":null,"errorMessage":"Failed to get file content type","messagePattern":"Failed to get file content type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/playground-ui/src/lib/file/contentTypeFromUrl.ts","lineNumber":34,"sourceCode":"    return EXTENSION_TO_MIME[extension.toLowerCase()];\n  }\n};\n\nexport const getFileContentType = async (url: string) => {\n  // Cloud-storage URIs are fetched server-side by the model provider (e.g. Vertex\n  // AI for `gs://`, Bedrock for `s3://`); the browser cannot HEAD them, so infer\n  // the content type from the extension directly.\n  if (NON_FETCHABLE_REMOTE_SCHEMES.some(scheme => url.startsWith(scheme))) {\n    return contentTypeFromExtension(url);\n  }\n\n  try {\n    const response = await fetch(url, {\n      method: 'HEAD',\n    });\n\n    if (!response.ok) {\n      throw new Error('Failed to get file content type');\n    }\n\n    const contentType = response.headers.get('content-type');\n\n    if (!contentType) {\n      throw new Error('Failed to get file content type');\n    }\n\n    return contentType;\n  } catch {\n    // fetch failed — try to infer content type from the file extension\n    return contentTypeFromExtension(url);\n  }\n};\n","sourceCodeStart":16,"sourceCodeEnd":49,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/playground-ui/src/lib/file/contentTypeFromUrl.ts#L16-L49","documentation":"getFileContentType performs a HEAD request against a URL and uses the response's content-type header as the file's content type. This error is thrown when the HEAD request completes but returns a non-2xx status, meaning the server responded but did not serve the file, so no trustworthy content type is available.","triggerScenarios":"Calling getFileContentType(url) where fetch(url, { method: 'HEAD' }) resolves with response.ok === false — e.g. the file URL returns 404 (file deleted), 403 (no permission), or the storage endpoint rejects HEAD requests with 405.","commonSituations":"Files uploaded to storage that were later removed or expired (presigned URL expired), private buckets where the caller lacks read access, or servers/s CDNs that do not allow the HEAD method.","solutions":["Verify the URL is still valid and the file exists (open it in a browser or curl -I <url>).","Check permissions/credentials for private storage — generate a fresh presigned URL if it expired.","If the server rejects HEAD (405), fall back to inferring the type from the file extension (contentTypeFromExtension).","Wrap the call and rely on the built-in catch path: a fetch failure falls back to extension-based inference, but an HTTP error status surfaces here — handle it explicitly."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"const ok = await fetch(url, { method: 'HEAD' }).then(r => r.ok).catch(() => false);\nif (!ok) console.warn(`HEAD failed for ${url}; will need extension fallback`);","typeGuard":null,"tryCatchPattern":"let contentType: string;\ntry {\n  contentType = await getFileContentType(url);\n} catch {\n  contentType = contentTypeFromExtension(url) ?? 'application/octet-stream';\n}","preventionTips":["Check file availability (curl -I) when URLs come from expiring presigned storage links.","Verify the storage/CDN allows HEAD requests (some return 405).","Regenerate presigned URLs before use rather than caching them past expiry."],"tags":["network","http","content-type","fetch","files"],"backgroundTag":"http-request-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}