jackwener/OpenCLI · error · ArgumentError
Unsupported remote image format "${normalizedContentType ||
Error message
Unsupported remote image format "${normalizedContentType || 'unknown'}". Supported: jpg, jpeg, png, gif, webp What it means
resolveImageExtension determines the file extension for a downloaded remote image from its Content-Type header, falling back to the URL pathname extension. If neither maps to a supported type (jpg/jpeg/png/gif/webp) it throws ArgumentError. This ensures the file saved for the composer upload has an extension X accepts.
Source
Thrown at clis/twitter/utils.js:73
/**
* Resolve the file extension to use when persisting a remote image: prefer
* Content-Type, fall back to URL pathname.
*/
export function resolveImageExtension(url, contentType) {
const normalizedContentType = (contentType || '').split(';')[0].trim().toLowerCase();
if (normalizedContentType && CONTENT_TYPE_TO_EXTENSION[normalizedContentType]) {
return CONTENT_TYPE_TO_EXTENSION[normalizedContentType];
}
try {
const pathname = new URL(url).pathname;
const ext = path.extname(pathname).toLowerCase();
if (SUPPORTED_IMAGE_EXTENSIONS.has(ext))
return ext;
} catch {
// Fall through to the final error below.
}
throw new ArgumentError(
`Unsupported remote image format "${normalizedContentType || 'unknown'}". Supported: jpg, jpeg, png, gif, webp`,
);
}
/**
* Download a remote image to a per-call tmp directory. Returns the absolute
* path on success. Caller owns the tmp dir and must clean it up. Throws
* {@link ArgumentError} on bad input or download failure.
*
* @returns {Promise<{ absPath: string, cleanupDir: string }>}
*/
export async function downloadRemoteImage(imageUrl) {
let parsed;
try {
parsed = new URL(imageUrl);
} catch {
throw new ArgumentError(`Invalid image URL: ${imageUrl}`);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Use a direct image URL (verify with `curl -sI <url>` that content-type is image/jpeg|png|gif|webp).
- Request a non-AVIF variant: add Accept: image/jpeg or use the original file URL many CDNs expose (e.g. strip format params).
- Convert the image locally first (download, `magick` convert to png/jpg) and pass a local path instead.
- If content-type is HTML, fix the underlying URL — it's probably a login wall or 404 page.
Example fix
// before
await postWithImageFromUrl('https://cdn.example.com/i/abc?fmt=avif'); // image/avif
// after
const res = await fetch('https://cdn.example.com/i/abc?fmt=jpg');
// confirm content-type is image/jpeg before calling Defensive patterns
Strategy: validation
Validate before calling
const head = await fetch(imageUrl, { method: 'HEAD' });
const type = head.headers.get('content-type') || '';
if (!/^image\/(jpeg|png|gif|webp)$/.test(type)) {
throw new Error(`URL serves "${type}", need jpeg/png/gif/webp: ${imageUrl}`);
} Try / catch
try {
await postWithImageFromUrl(imageUrl);
} catch (err) {
if (err instanceof ArgumentError && /Unsupported remote image format/.test(err.message)) {
const local = await downloadAndConvertToPng(imageUrl);
return postWithImage(local);
}
throw err;
} Prevention
- Use direct image URLs; check content-type with `curl -sI` first.
- Avoid URLs negotiated to image/avif; request jpg/png variants explicitly.
- If content-type is text/html, the URL is a login/error page — fix the source URL.
When it happens
Trigger: Downloading a remote image whose Content-Type is not a supported image type — e.g. text/html (an error/redirect page), application/octet-stream, image/avif, image/heic, or a missing content-type with a URL lacking a recognized extension.
Common situations: URL actually returns an HTML login/error page instead of an image; CDN serving AVIF via content negotiation; image hosts returning octet-stream with extensionless URLs; signed URLs whose path has no extension.
Related errors
- Unsupported image format "${ext}". Supported: jpg, jpeg, png
- Detached HEAD — checkout a branch first
- 12306 queryByTrainNo returned HTTP ${resp.status}
- 12306 queryByTrainNo returned non-JSON body
- 12306 ${endpoint} returned non-JSON body
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3c729a706aee0ada.
Report an issue: GitHub.