{"record":{"id":"f25b04a7e20f2b95","repo":"libnyanpasu/clash-nyanpasu","slug":"no-content-type","errorCode":null,"errorMessage":"no content-type","messagePattern":"no content-type","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/tauri/src/server/mod.rs","lineNumber":113,"sourceCode":"        Some(_) => {\n            let span = tracing::span!(tracing::Level::DEBUG, \"read_cache_file\", path = ?cache_file);\n            let _enter = span.enter();\n            match read_cache_file(&cache_file).await {\n                Ok((mime, bytes)) => return Ok((mime, bytes)),\n                Err(e) => {\n                    tracing::error!(\"failed to read cache file: {}\", e);\n                    remove_cache_file(&cache_file).await;\n                }\n            }\n        }\n        _ => (),\n    }\n    let client = get_reqwest_client()?;\n    let response = client.get(url).send().await?.error_for_status()?;\n    let mime = response\n        .headers()\n        .get(\"content-type\")\n        .ok_or(anyhow!(\"no content-type\"))?\n        .to_str()?\n        .to_string();\n\n    let bytes = response.bytes().await?;\n    let data = CacheFile {\n        mime: Cow::Owned(mime),\n        bytes,\n    };\n    if let Err(e) = write_cache_file(&cache_file, &data).await {\n        tracing::error!(\"failed to write cache file: {}\", e);\n    }\n    Ok(data\n        .try_into()\n        .expect(\"It's impossible to fail, if failed, it must a bug, or memory corruption\"))\n}\n\n#[tracing_attributes::instrument]\nasync fn cache_icon(query: Query<CacheIcon>) -> Response<Body> {","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/server/mod.rs#L95-L131","documentation":"cache_icon_inner downloads an icon over HTTP and needs the response's content-type header to determine the MIME type for the cache file. If the server returns a 2xx response without a Content-Type header, it throws anyhow \"no content-type\".","triggerScenarios":"Caching a proxy-group/provider icon whose URL points to a server (bare object store, misconfigured CDN/nginx, raw file server) that omits Content-Type on a successful response.","commonSituations":"Subscription providers hosting icons on servers with no MIME types configured, self-hosted file servers, or services replying with headerless 200s.","solutions":["Fix the icon server to send a correct Content-Type header.","Point the icon URL at a host serving proper MIME types.","Fall back to a sniffed or default MIME type when the header is missing.","Add the header via a reverse proxy in front of the icon host."],"exampleFix":"// before\nlet mime = response.headers().get(\"content-type\").ok_or(anyhow!(\"no content-type\"))?.to_str()?.to_string();\n// after\nlet mime = response.headers().get(\"content-type\")\n    .and_then(|v| v.to_str().ok())\n    .unwrap_or(\"application/octet-stream\")\n    .to_string();","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await invoke('cache_icon', { url });\n} catch (e) {\n  if (String(e).includes('no content-type')) {\n    usePlaceholderIcon(url);\n  } else throw e;\n}","preventionTips":["Host icons on servers that send proper MIME headers","Prefer well-known CDN/image hosts for icon URLs","Configure nginx mime.types correctly on self-hosted icons"],"tags":["http","headers","icons","cache"],"backgroundTag":"missing-required-config-field","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}