jackwener/OpenCLI · error · Error
target already exists
Error message
target already exists
What it means
reserveAudioFile refuses to overwrite an existing file: before taking the exclusive (wx-flag) lock, it checks fs.existsSync(target) and throws Error('target already exists'). The catch re-wraps it as CommandExecutionError('MiniMax music cannot reserve output file <target>: target already exists'). The same check runs again after locking to detect races, in which case the message is 'target appeared during reservation'.
Source
Thrown at clis/minimax/utils.js:188
export function resolveOutputDir(value) {
const raw = String(value ?? '').trim();
if (!raw) return path.join(os.homedir(), 'Music', 'minimax');
if (raw === '~') return os.homedir();
if (raw.startsWith('~/')) return path.join(os.homedir(), raw.slice(2));
if (raw.startsWith('~')) throw new ArgumentError(`Unsupported home-directory path: ${raw}`);
return path.resolve(raw);
}
export function reserveAudioFile(dir, model, format, now = new Date()) {
const stamp = now.toISOString().replace(/[-:]/g, '').replace(/\.\d+Z$/, 'Z');
const target = path.join(dir, `${model}-${stamp}.${format}`);
const lock = `${target}.lock`;
const staging = `${target}.${process.pid}.${randomUUID()}.tmp`;
try {
fs.mkdirSync(dir, { recursive: true });
if (!fs.statSync(dir).isDirectory()) throw new Error('not a directory');
fs.accessSync(dir, fs.constants.W_OK);
if (fs.existsSync(target)) throw new Error('target already exists');
fs.writeFileSync(lock, String(process.pid), { flag: 'wx', mode: 0o600 });
if (fs.existsSync(target)) {
fs.rmSync(lock, { force: true });
throw new Error('target appeared during reservation');
}
return { target, lock, staging };
} catch (error) {
throw new CommandExecutionError(`MiniMax music cannot reserve output file ${target}: ${error?.message ?? error}`);
}
}
export function commitAudioFile(reservation, bytes) {
try {
fs.writeFileSync(reservation.staging, bytes, { flag: 'wx', mode: 0o600 });
// A same-filesystem hard link publishes the complete staging inode and
// fails if target already exists on POSIX and Windows alike.
fs.linkSync(reservation.staging, reservation.target);
cleanupAudioFile(reservation);View on GitHub (pinned to 49907e53dc)
Solutions
- Wait at least one second and re-run so the ISO-timestamp filename differs
- Choose a different output directory or move/rename the existing file
- Delete the stale target file if it is from a failed earlier run: rm <target> (also remove <target>.lock if left behind)
- Wrap the call in a retry that regenerates with a new Date() to get a fresh stamp
Example fix
// before: second call in the same second collides
let r = reserveAudioFile(dir, model, 'mp3'); // throws 'target already exists'
// after: retry with a fresh timestamp
let r;
for (let i = 0; !r; i++) {
try { r = reserveAudioFile(dir, model, 'mp3'); }
catch (e) { if (!String(e.message).includes('target already exists') || i > 2) throw e; await new Promise(s => setTimeout(s, 1100)); }
} Defensive patterns
Strategy: retry
Validate before calling
import * as fs from 'node:fs';
function targetFree(dir, model, format, now = new Date()) {
const stamp = now.toISOString().replace(/[-:]/g, '').replace(/\.\d+Z$/, 'Z');
return !fs.existsSync(require('node:path').join(dir, `${model}-${stamp}.${format}`));
}
// if (!targetFree(dir, model, 'mp3')) wait or pick another dir before calling Try / catch
async function reserveWithRetry(dir, model, format, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try { return reserveAudioFile(dir, model, format, new Date()); }
catch (e) {
if (!String(e.message).includes('target already exists') || i === attempts - 1) throw e;
await new Promise(s => setTimeout(s, 1100)); // fresh timestamp next try
}
}
} Prevention
- Avoid rapid successive generations of the same model+format within one second
- Clean up stale targets and .lock files from failed runs before rerunning
- Write output to a fresh/timestamped or run-scoped directory in pipelines
- Catch the wrapped CommandExecutionError and surface the target path so operators can clear it
When it happens
Trigger: The generated filename '<model>-<timestamp>.<format>' already exists in dir — typically two generations within the same second producing an identical ISO-stamp name, or a rerun of the same command.
Common situations: Running the CLI twice in quick succession (same model, same format, same second); a previous partially-failed run left the target file; automated pipelines invoking generation more than once per second.
Related errors
- not a directory
- Refusing to overwrite existing Pixiv download: ${plan.finalP
- Refusing to overwrite existing Pixiv download: ${destPath}
- Verify command returned no metric for baseline
- File not found: ${path}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9ec4c8189e8af58e.
Report an issue: GitHub.