jackwener/OpenCLI · error · CliError

EMPTY_RESPONSE

EMPTY_RESPONSE

Error message

EMPTY_RESPONSE

What it means

The yollomi object-remover command throws EMPTY_RESPONSE when /api/ai/object-remover returns no result image. It reads data.image or data.images[0]; if both are missing, no removal output was produced and the CLI aborts before download.

Source

Thrown at clis/yollomi/object-remover.js:31

    description: 'Remove unwanted objects from images (3 credits)',
    domain: YOLLOMI_DOMAIN,
    strategy: Strategy.COOKIE,
    args: [
        { name: 'image', positional: true, required: true, help: 'Image URL' },
        { name: 'mask', positional: true, required: true, help: 'Mask image URL (white = area to remove)' },
        { name: 'output', default: './yollomi-output', help: 'Output directory' },
        { name: 'no-download', type: 'boolean', default: false, help: 'Only show URL' },
    ],
    columns: ['status', 'file', 'size', 'url'],
    func: async (page, kwargs) => {
        log.status('Removing object...');
        const data = await yollomiPost(page, '/api/ai/object-remover', {
            image: kwargs.image,
            mask: kwargs.mask,
        });
        const url = data.image || (data.images?.[0]);
        if (!url)
            throw new CliError('EMPTY_RESPONSE', 'No result', 'Check image and mask');
        if (kwargs['no-download'])
            return [{ status: 'removed', file: '-', size: '-', url }];
        try {
            const filename = `yollomi_removed_${Date.now()}.png`;
            const { path: fp, size } = await downloadOutput(url, kwargs.output, filename);
            return [{ status: 'saved', file: path.relative('.', fp), size: fmtBytes(size), url }];
        }
        catch {
            return [{ status: 'download-failed', file: '-', size: '-', url }];
        }
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the mask matches the input image dimensions and format (per the hint)
  2. Ensure both image and mask are publicly accessible valid files
  3. Retry — transient failures may return empty responses
  4. Log the raw API response to check for ignored error fields
  5. Update field extraction if the site API response changed

Example fix

// before
const url = data.image || (data.images?.[0]);
if (!url) throw new CliError('EMPTY_RESPONSE', 'No result', 'Check image and mask');
// after
if (data.error) throw new CliError('API_ERROR', data.error, 'Check object-remover API response');
const url = data.image || data.result || (data.images?.[0]);
if (!url) throw new CliError('EMPTY_RESPONSE', 'No result', 'Check image and mask');
Defensive patterns

Strategy: validation

Validate before calling

const imgMeta = await probe(kwargs.image), maskMeta = await probe(kwargs.mask);
if (imgMeta.width !== maskMeta.width || imgMeta.height !== maskMeta.height)
  throw new Error(`mask ${maskMeta.width}x${maskMeta.height} does not match image ${imgMeta.width}x${imgMeta.height}`);

Type guard

function hasRemovalResult(d) {
  return d != null && (typeof d.image === 'string' || (Array.isArray(d.images) && typeof d.images[0] === 'string'));
}

Try / catch

try {
  const rows = await opencli.yollomi['object-remover']({ image, mask });
} catch (e) {
  if (e.code === 'EMPTY_RESPONSE') {
    console.error(`${e.message}: ${e.hint} — verify mask dimensions match the image`);
  } else throw e;
}

Prevention

When it happens

Trigger: POSTing { image: kwargs.image, mask: kwargs.mask } yields a 200 with no image fields — commonly a mask/image mismatch (different dimensions), an unfetchable URL, or a changed response schema.

Common situations: Mask dimensions not matching the input image; mask format not accepted by the endpoint; input image URL private or expired; silent server-side failure with empty payload.

Related errors


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