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

  1. Wait at least one second and re-run so the ISO-timestamp filename differs
  2. Choose a different output directory or move/rename the existing file
  3. Delete the stale target file if it is from a failed earlier run: rm <target> (also remove <target>.lock if left behind)
  4. 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

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


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