diff --git a/src/commands/image/generate.ts b/src/commands/image/generate.ts index b530a72b..e05a0e81 100644 --- a/src/commands/image/generate.ts +++ b/src/commands/image/generate.ts @@ -142,6 +142,16 @@ export default defineCommand({ process.stderr.write('[Model: image-01]\n'); } + // The API answers 200 with an empty image list when every image is rejected. + // Without this check the command reports the --out path as saved and exits 0 + // even though nothing was written (see ERRORS.md, `mmx image generate`). + if (response.data.success_count === 0) { + throw new CLIError( + 'Image generation failed: all images were rejected (content policy or model error).', + ExitCode.GENERAL, + ); + } + const saved: string[] = []; if (outPath) { diff --git a/test/commands/image/generate.test.ts b/test/commands/image/generate.test.ts index 1cdd56a4..fbc4996b 100644 --- a/test/commands/image/generate.test.ts +++ b/test/commands/image/generate.test.ts @@ -1,5 +1,9 @@ import { describe, it, expect } from 'bun:test'; +import { existsSync, rmSync } from 'fs'; +import { tmpdir } from 'os'; +import { join } from 'path'; import { default as generateCommand } from '../../../src/commands/image/generate'; +import { createMockServer, jsonResponse } from '../../helpers/mock-server'; const baseConfig = { apiKey: 'test-key', @@ -91,4 +95,30 @@ describe('image generate command', () => { expect(parsed.request.seed).toBe(42); expect(parsed.request.model).toBe('image-01'); }); + + it('fails when the API rejects every image instead of reporting a saved file', async () => { + const server = createMockServer({ + routes: { + '/v1/image_generation': () => jsonResponse({ + id: 'req-1', + data: { image_urls: [], task_id: 'task-1', success_count: 0, failed_count: 1 }, + base_resp: { status_code: 0, status_msg: 'success' }, + }), + }, + }); + const outPath = join(tmpdir(), `mmx-image-rejected-${process.pid}-${Date.now()}.jpg`); + + try { + await expect( + generateCommand.execute( + { ...baseConfig, baseUrl: server.url, quiet: true }, + { ...baseFlags, quiet: true, prompt: 'A cat', out: outPath }, + ), + ).rejects.toThrow('Image generation failed: all images were rejected'); + expect(existsSync(outPath)).toBe(false); + } finally { + rmSync(outPath, { force: true }); + server.close(); + } + }); });