jackwener/OpenCLI · error · CommandExecutionError

MiniMax music cannot reserve output file ${target}: ${error?

Error message

MiniMax music cannot reserve output file ${target}: ${error?.message ?? error}

What it means

reserveAudioFile wraps every failure of the reservation sequence (mkdir, stat, W_OK access check, exclusive lock creation, TOCTOU re-check) in a CommandExecutionError: 'MiniMax music cannot reserve output file <target>: <cause>'. The cause string is appended via error?.message ?? error, so the root reason always appears after the colon.

Source

Thrown at clis/minimax/utils.js:196

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}`);
    }
}

export function cleanupAudioFile(reservation) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the cause after the colon: if it mentions EEXIST/.lock, delete the stale `<target>.lock` file and retry.
  2. If the cause is 'not a directory' or permission denied, pass a --output path that is an existing writable directory.
  3. Verify write access: `touch <dir>/.writetest`, then fix ownership/ACLs if it fails.
  4. If two jobs collide concurrently, serialize them or use separate output directories.

Example fix

// before
$ minimax music --output /etc  # not writable
Error: MiniMax music cannot reserve output file /etc/minimax-music-...: EACCES

// after
$ minimax music --output ~/Music/minimax
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
function ensureWritableOutputDir(dir) {
  const resolved = path.resolve(String(dir ?? '').replace(/^~(?=$|\/)/, os.homedir()));
  fs.mkdirSync(resolved, { recursive: true });
  if (!fs.statSync(resolved).isDirectory()) throw new Error(`not a directory: ${resolved}`);
  fs.accessSync(resolved, fs.constants.W_OK);
  return resolved;
}

Try / catch

try {
  runMinimaxMusic();
} catch (e) {
  const m = /cannot reserve output file .*: (.+)$/.exec(e.message);
  if (m && m[1].includes('EEXIST')) {
    fs.rmSync(`${target}.lock`, { force: true }); // stale lock from crashed run
  } else if (m && /EACCES|not a directory/.test(m[1])) {
    console.error('Fix --output: must be a writable directory');
  } else { throw e; }
}

Prevention

When it happens

Trigger: Any failure inside reserveAudioFile's try block: the --output path is not a directory, the directory is not writable (fs.accessSync W_OK fails), fs.writeFileSync with flag 'wx' fails because <target>.lock already exists (stale lock from a crashed run), or the target appeared during the reservation race.

Common situations: --output pointing to an existing regular file instead of a directory; read-only or permission-restricted output directories (restricted CI workspace, ~/Music/minimax owned by another user); leftover .lock files from killed commands making 'wx' creation throw EEXIST.

Related errors


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