jackwener/OpenCLI · error · Error
target appeared during reservation
Error message
target appeared during reservation
What it means
reserveAudioFile in clis/minimax/utils.js reserves a unique timestamped output path for generated MiniMax music using a write-exclusive lock file. After acquiring the lock it re-checks the target; if the target file appeared between the first existence check and lock acquisition, it releases the lock and throws 'target appeared during reservation', wrapped as CommandExecutionError 'MiniMax music cannot reserve output file <target>: ...'. This is a deliberate TOCTOU guard ensuring the same-second output file is never silently overwritten.
Source
Thrown at clis/minimax/utils.js:192
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);
return reservation.target;
} catch (error) {
cleanupAudioFile(reservation);
throw new CommandExecutionError(`MiniMax music could not atomically write ${reservation.target}: ${error?.message ?? error}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Rerun the command — the timestamp advances, producing a different filename and resolving the collision.
- Use a distinct --output directory per concurrent job to eliminate collisions.
- Serialize concurrent music generations (flock, job queue) so only one reserves a file at a time.
- If the collision persists, remove or rename the target file at that path and retry.
Example fix
// before (collides when run in parallel) minimax music --prompt 'lofi' --output ./out & minimax music --prompt 'lofi' --output ./out & // after (per-job output dir avoids same-second collision) minimax music --prompt 'lofi' --output ./out/job-$$_$(date +%s%N)
Defensive patterns
Strategy: try-catch
Validate before calling
const target = path.join(dir, `${model}-${stamp}.${format}`);
if (fs.existsSync(target)) throw new Error(`output already exists: ${target}`);
fs.accessSync(dir, fs.constants.W_OK); Try / catch
try {
const reservation = reserveAudioFile(dir, model, format);
// ... generate and commit
} catch (e) {
if (String(e.message).includes('target appeared during reservation')) {
// concurrent run won the race: retry with a fresh timestamp or another dir
} else { throw e; }
} Prevention
- Give each concurrent job its own --output directory.
- Do not launch two music generations with the same output dir in the same second.
- Serialize invocations in scripts/CI with a mutex or job queue.
- Retry once on this error — the next timestamp usually differs.
When it happens
Trigger: A concurrent MiniMax music command created a file at the identical timestamped path `${model}-${stamp}.${format}` between the first fs.existsSync(target) check and the post-lock re-check — e.g. two music generations started in the same second writing to the same --output directory.
Common situations: Running two CLI music generation commands in parallel (scripts, CI, cron) sharing an output directory; same-second filename collisions since the name has only second-level precision; retry loops launching two invocations nearly simultaneously.
Related errors
- File not found: ${path}
- File must be a readable text file: ${path}
- File could not be read: ${path}
- Browser reported a completed download but the file is missin
- MiniMax music cannot reserve output file ${target}: ${error?
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9b4f4f33bda6f53b.
Report an issue: GitHub.