jackwener/OpenCLI · error · CliError
EMPTY_RESPONSE
EMPTY_RESPONSE
Error message
EMPTY_RESPONSE
What it means
The yollomi face-swap command throws EMPTY_RESPONSE when /api/ai/face-swap returns no image. The code checks data.image then data.images[0]; absence of both means the swap produced no output, so it aborts rather than downloading an undefined URL.
Source
Thrown at clis/yollomi/face-swap.js:32
description: 'Swap faces between two photos (3 credits)',
domain: YOLLOMI_DOMAIN,
strategy: Strategy.COOKIE,
args: [
{ name: 'source', required: true, help: 'Source face image URL' },
{ name: 'target', required: true, help: 'Target photo URL' },
{ 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('Swapping faces...');
const data = await yollomiPost(page, '/api/ai/face-swap', {
swap_image: kwargs.source,
input_image: kwargs.target,
});
const url = data.image || (data.images?.[0]);
if (!url)
throw new CliError('EMPTY_RESPONSE', 'No result', 'Make sure both images contain clear faces');
if (kwargs['no-download'])
return [{ status: 'swapped', file: '-', size: '-', url }];
try {
const filename = `yollomi_faceswap_${Date.now()}.jpg`;
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
- Retry with clearer, front-facing photos in both images (per the hint)
- Verify you did not swap `--source` and `--target` arguments
- Ensure both image URLs/files are publicly accessible and valid formats
- Log the raw API response to check for ignored error fields
- Re-check response field names if the site API was updated
Example fix
// before
const url = data.image || (data.images?.[0]);
if (!url) throw new CliError('EMPTY_RESPONSE', 'No result', 'Make sure both images contain clear faces');
// after
if (data.error) throw new CliError('API_ERROR', data.error, 'Check face-swap API response');
const url = data.image || data.output || (data.images?.[0]);
if (!url) throw new CliError('EMPTY_RESPONSE', 'No result', 'Make sure both images contain clear faces'); Defensive patterns
Strategy: validation
Validate before calling
for (const u of [source, target]) {
const res = await fetch(u, { method: 'HEAD' });
if (!res.ok) throw new Error(`image not reachable: ${u}`);
} Type guard
function hasSwappedImage(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['face-swap']({ source, target });
} catch (e) {
if (e.code === 'EMPTY_RESPONSE') {
console.error(`Face swap failed: ${e.hint} — check --source/--target order and photo quality`);
} else throw e;
} Prevention
- Use front-facing, unoccluded face photos for both inputs
- Double-check --source (swap image) vs --target (base image) order
- HEAD-check both image URLs first
- Retry once on EMPTY_RESPONSE before giving up
When it happens
Trigger: POSTing { swap_image, input_image } to /api/ai/face-swap yields a 200 response without image fields — typically one of the two images has no detectable face, an image failed to fetch server-side, or the schema changed.
Common situations: Input photos where faces are too small, occluded, or non-frontal; swapped source/target arguments by mistake; images behind auth walls the server cannot fetch; site API update.
Related errors
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3b7ba416ccadd0ae.
Report an issue: GitHub.