jackwener/OpenCLI · error · ArgumentError

Unsupported image format "${ext}". Supported: jpg, jpeg, png

Error message

Unsupported image format "${ext}". Supported: jpg, jpeg, png, webp

What it means

validateImagePaths throws ArgumentError when an image path's lowercased extension is not in SUPPORTED_IMAGE_EXTENSIONS (.jpg, .jpeg, .png, .webp). The check runs on path.extname before any filesystem access, so extension — not file content — is what fails.

Source

Thrown at clis/xianyu/publish.js:68

    const condition = requireText(value, 'condition');
    if (!CONDITION_CHOICES.includes(condition)) {
        throw new ArgumentError(`xianyu publish condition must be one of: ${CONDITION_CHOICES.join(', ')}`);
    }
    return condition;
}

function validateImagePaths(raw) {
    if (!raw) return [];
    const paths = String(raw).split(',').map((item) => item.trim()).filter(Boolean);
    if (paths.length === 0) return [];
    if (paths.length > MAX_IMAGES) {
        throw new ArgumentError(`xianyu publish images supports at most ${MAX_IMAGES} files`);
    }
    return paths.map((item) => {
        const absPath = path.resolve(item);
        const ext = path.extname(absPath).toLowerCase();
        if (!SUPPORTED_IMAGE_EXTENSIONS.has(ext)) {
            throw new ArgumentError(`Unsupported image format "${ext}". Supported: jpg, jpeg, png, webp`);
        }
        const stat = fs.statSync(absPath, { throwIfNoEntry: false });
        if (!stat || !stat.isFile()) {
            throw new ArgumentError(`Not a valid image file: ${absPath}`);
        }
        return absPath;
    });
}

function normalizePublishArgs(kwargs) {
    const price = parsePositivePrice(kwargs.price, 'price');
    if (price == null) {
        throw new ArgumentError('xianyu publish price cannot be empty');
    }
    const normalized = {};
    normalized.title = requireText(kwargs.title, 'title');
    normalized.description = requireText(kwargs.description, 'description');
    normalized.price = price;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Convert the image to jpg/png/webp (e.g. sharp, ffmpeg, or macOS 'sips -s format jpeg')
  2. Do not merely rename — re-encode, since content must match the extension
  3. Filter the image list against the supported extension set before calling publish

Example fix

// before
await publish({ images: 'IMG_0001.HEIC' });
// after
// $ sips -s format jpeg IMG_0001.HEIC --out IMG_0001.jpg
await publish({ images: 'IMG_0001.jpg' });
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = new Set(['.jpg', '.jpeg', '.png', '.webp']);
for (const p of images.split(',')) {
  const ext = path.extname(p.trim()).toLowerCase();
  if (!SUPPORTED.has(ext)) throw new Error(`Convert ${p}: unsupported format ${ext}`);
}

Type guard

function isSupportedImage(p) {
  return ['.jpg', '.jpeg', '.png', '.webp'].includes(path.extname(p).toLowerCase());
}

Try / catch

try {
  await publish({ images });
} catch (e) {
  if (e instanceof ArgumentError && /Unsupported image format/.test(e.message)) {
    console.error('Convert unsupported files to jpg/png/webp before publishing');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing images like 'photo.HEIC' (iPhone), 'cat.gif', 'screenshot.bmp', or extension-less files; any ext not in {'.jpg','.jpeg','.png','.webp'} throws.

Common situations: iOS HEIC photos not converted before upload, GIFs/BMPs from screenshots, newer formats like .avif, or paths whose extensions were stripped after copy/move.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/b5a49113bd8e164e. Report an issue: GitHub.