jackwener/OpenCLI · error · CommandExecutionError

Failed to read image dimensions for ${filePath}

Error message

Failed to read image dimensions for ${filePath}

What it means

readImageDimensions parses PNG/WebP/JPEG headers to obtain width/height required for the private upload; when none of the format parsers recognizes the bytes this error is thrown, since Instagram needs declared media dimensions.

Source

Thrown at clis/instagram/_shared/private-publish.js:269

    }
    if (chunkType === 'VP8L' && bytes.length >= 25) {
        const bits = bytes.readUInt32LE(21);
        return {
            width: (bits & 0x3fff) + 1,
            height: ((bits >> 14) & 0x3fff) + 1,
        };
    }
    return null;
}
function readImageDimensions(filePath, bytes) {
    const ext = path.extname(filePath).toLowerCase();
    const dimensions = ext === '.png'
        ? readPngDimensions(bytes)
        : ext === '.webp'
            ? readWebpDimensions(bytes)
            : readJpegDimensions(bytes);
    if (!dimensions) {
        throw new CommandExecutionError(`Failed to read image dimensions for ${filePath}`);
    }
    return dimensions;
}
export function readImageAsset(filePath) {
    const bytes = fs.readFileSync(filePath);
    const { width, height } = readImageDimensions(filePath, bytes);
    return {
        filePath,
        fileName: path.basename(filePath),
        mimeType: inferMimeType(filePath),
        width,
        height,
        byteLength: bytes.length,
        bytes,
    };
}
export function isInstagramFeedAspectRatioAllowed(width, height) {
    const ratio = width / Math.max(height, 1);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the file is a valid, non-corrupt PNG/WebP/JPEG (open it locally or run `file image.png`)
  2. Rename the file so its extension matches the actual format
  3. Re-export or re-download the image
  4. Convert unsupported formats to JPEG/PNG before upload

Example fix

// before
await upload({ media: 'logo.svg' });
// after
// $ magick logo.svg logo.png
await upload({ media: 'logo.png' });
Defensive patterns

Strategy: validation

Validate before calling

const bytes = fs.readFileSync(filePath);
if (bytes.length < 16) throw new Error(`${filePath} is not a readable image`);
const sig = bytes.subarray(0, 4).toString('hex');
const ok = sig === '89504e47' || bytes.subarray(0,4).toString() === 'RIFF' || bytes[0] === 0xFF && bytes[1] === 0xD8;
if (!ok) throw new Error(`${filePath} is not PNG/WebP/JPEG`);

Type guard

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

Try / catch

try {
  await publish(cfg);
} catch (e) {
  if (/Failed to read image dimensions/.test(e.message)) {
    // re-encode the asset and retry
    execSync(`magick ${cfg.media} ${cfg.media.replace(/\.\w+$/, '.png')}`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling prepareImageAssetForPrivateUpload / readImageAsset with a file whose extension-branch parser (png/webp/jpeg) fails: corrupt file, unsupported extension treated as jpeg, truncated download, or zero-byte file.

Common situations: A .jpg file that is actually another format, an SVG or GIF passed where a raster image is expected, partially downloaded image, file with wrong extension.

Related errors


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