jackwener/OpenCLI · error · ArgumentError
Unsupported image format "${ext}". Supported: jpg, png, gif,
Error message
Unsupported image format "${ext}". Supported: jpg, png, gif, webp What it means
ArgumentError from validateImagePaths: the image file exists but its extension (lowercased) is not a key in SUPPORTED_EXTENSIONS (jpg, png, gif, webp). XHS's uploader only accepts these formats, so the CLI rejects other files up front.
Source
Thrown at clis/xiaohongshu/publish.js:132
&& typeof value.session === 'string'
&& Object.prototype.hasOwnProperty.call(value, 'data')
) {
return value.data;
}
return value;
}
/**
* Validate image paths: check existence and extension.
* Returns resolved absolute paths.
*/
function validateImagePaths(filePaths) {
return filePaths.map((filePath) => {
const absPath = path.resolve(filePath);
if (!fs.existsSync(absPath))
throw new ArgumentError(`Image file not found: ${absPath}`);
const ext = path.extname(absPath).toLowerCase();
if (!SUPPORTED_EXTENSIONS[ext]) {
throw new ArgumentError(`Unsupported image format "${ext}". Supported: jpg, png, gif, webp`);
}
return absPath;
});
}
/** CSS selector for image-accepting file inputs. */
const IMAGE_INPUT_SELECTOR = 'input[type="file"][accept*="image"],'
+ 'input[type="file"][accept*=".jpg"],'
+ 'input[type="file"][accept*=".jpeg"],'
+ 'input[type="file"][accept*=".png"],'
+ 'input[type="file"][accept*=".gif"],'
+ 'input[type="file"][accept*=".webp"]';
/**
* Upload images via CDP DOM.setFileInputFiles — Chrome reads files directly
* from the local filesystem, avoiding base64 payload size limits.
*
* Falls back to the legacy base64 DataTransfer approach if the extension
* does not support set-file-input (e.g. older extension version).
*/View on GitHub (pinned to 49907e53dc)
Solutions
- Convert the image to jpg/png/webp (e.g. `sips -s format jpeg in.heic --out out.jpg` or ImageMagick `convert`).
- Rename `.jpeg` to `.jpg` if that is the only issue — or convert if .jpeg is not in the supported map.
- Add the correct extension if the file was downloaded without one.
- Check the extension actually matches the file content (file command) to avoid upload failure later.
Example fix
// before
await xhs.publish({ images: ['photo.heic'] });
// after
// convert first: magick photo.heic photo.jpg
await xhs.publish({ images: ['photo.jpg'] }); Defensive patterns
Strategy: validation
Validate before calling
const OK = new Set(['.jpg', '.png', '.gif', '.webp']);
for (const p of images) {
const ext = require('path').extname(p).toLowerCase();
if (!OK.has(ext)) throw new Error(`Convert ${p} (${ext}) to jpg/png/gif/webp first`);
} Type guard
function isSupportedImage(p) {
return ['.jpg', '.png', '.gif', '.webp']
.includes(require('path').extname(String(p)).toLowerCase());
} Try / catch
try {
await xhs.publish({ images });
} catch (err) {
if (err.message.startsWith('Unsupported image format')) {
console.error('Convert the file, e.g. magick in.heic out.jpg');
} else throw err;
} Prevention
- Convert HEIC/AVIF/TIFF photos to jpg before publishing
- Normalize .jpeg to .jpg in your pipeline
- Ensure downloaded images have proper extensions
- Validate extensions in a pre-publish step
When it happens
Trigger: Passing .jpeg, .bmp, .tiff, .heic, .avif, or extensionless files to publish; files downloaded without an extension; uppercase extensions are fine (extname is lowercased), but exotic ones are not.
Common situations: iPhone HEIC photos, .jpeg naming, screenshots saved as .tiff on macOS, or images with missing extensions from downloads.
Related errors
- weixin create-draft cover-image must be JPEG, PNG, GIF, or W
- --limit must be an integer between 1 and 100, got ${JSON.str
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3bdf2bc947b7f6ef.
Report an issue: GitHub.