itwanger/toBeBetterJavaer · error · Error
Unexpected content type: ${contentType}
Error message
Unexpected content type: ${contentType} What it means
Thrown by downloadImage() in scripts/convert-mdnice-images-to-cdn.js when a successfully downloaded (HTTP 2xx) response has a Content-Type that, after normalization (strip parameters, lowercase), is neither image/* nor application/octet-stream. This guard prevents uploading HTML error pages, XML, JSON, or text content to the OSS image prefix.
Source
Thrown at scripts/convert-mdnice-images-to-cdn.js:369
await worker(items[index], index);
}
});
await Promise.all(workers);
}
async function downloadImage(url) {
const response = await fetch(url, {
redirect: "follow",
headers: {
"User-Agent": "toBeBetterJavaer-image-cdn/1.0",
},
});
if (!response.ok) {
throw new Error(`Download failed with HTTP ${response.status}`);
}
const contentType = normalizeContentType(response.headers.get("content-type"));
if (contentType && !contentType.startsWith("image/") && contentType !== "application/octet-stream") {
throw new Error(`Unexpected content type: ${contentType}`);
}
const body = Buffer.from(await response.arrayBuffer());
if (body.length === 0) {
throw new Error("Downloaded file is empty");
}
return { body, contentType };
}
function normalizeContentType(contentType) {
if (!contentType) {
return "";
}
return contentType.split(";")[0].trim().toLowerCase();
}
function contentTypeForPath(filePath) {
const extension = path.extname(filePath).toLowerCase();
switch (extension) {View on GitHub (pinned to 6617f5fd0b)
Solutions
- Open the failing URL in a browser or `curl -I` it to see the real Content-Type
- If it is an HTML error/login page, the URL is not a direct image link — fix the Markdown reference to the actual asset URL or upload the image manually
- If the source genuinely serves the right bytes with a wrong type and you control the script, allow that MIME explicitly in downloadImage
Example fix
# before: page URL, returns text/html  # after: direct image asset URL 
Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(url, { method: "HEAD" });
const ct = (res.headers.get("content-type") || "").split(";")[0].trim().toLowerCase();
if (ct && !ct.startsWith("image/") && ct !== "application/octet-stream") console.warn(`Will be rejected: ${url} is ${ct}`); Type guard
const isAcceptableContentType = (ct) => !ct || ct.startsWith("image/") || ct === "application/octet-stream"; Try / catch
catch (err) { if (err.message.startsWith("Unexpected content type:")) { console.error("URL serves a page, not an image — fix the Markdown reference"); } else throw err; } Prevention
- Reference direct asset URLs (ending in .png/.jpg/etc.), never page URLs
- Spot-check new mdnice exports with curl -I before batch converting
- Keep the accepted-type check in mind when extending --domains to new sources
When it happens
Trigger: The source URL returns 200 with text/html (a soft-404 error page or a login page), application/json (API error payload), or text/plain. Only application/octet-stream and image/* pass; missing Content-Type passes because contentType is then empty.
Common situations: CDN error pages served with status 200; URL redirect chains landing on an HTML interstitial; anti-bot pages; the link pointing at a page rather than the raw image asset.
Related errors
- Download failed with HTTP ${response.status}
- Downloaded file is empty
- ${optionName} must be a positive integer
AI-assisted analysis of itwanger/toBeBetterJavaer@6617f5fd0b (2026-08-14).
Data as JSON: /api/errors/c89283981bd1a315.
Report an issue: GitHub.