{"record":{"id":"9b4f4f33bda6f53b","repo":"jackwener/OpenCLI","slug":"target-appeared-during-reservation","errorCode":null,"errorMessage":"target appeared during reservation","messagePattern":"target appeared during reservation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clis/minimax/utils.js","lineNumber":192,"sourceCode":"    if (raw.startsWith('~/')) return path.join(os.homedir(), raw.slice(2));\n    if (raw.startsWith('~')) throw new ArgumentError(`Unsupported home-directory path: ${raw}`);\n    return path.resolve(raw);\n}\n\nexport function reserveAudioFile(dir, model, format, now = new Date()) {\n    const stamp = now.toISOString().replace(/[-:]/g, '').replace(/\\.\\d+Z$/, 'Z');\n    const target = path.join(dir, `${model}-${stamp}.${format}`);\n    const lock = `${target}.lock`;\n    const staging = `${target}.${process.pid}.${randomUUID()}.tmp`;\n    try {\n        fs.mkdirSync(dir, { recursive: true });\n        if (!fs.statSync(dir).isDirectory()) throw new Error('not a directory');\n        fs.accessSync(dir, fs.constants.W_OK);\n        if (fs.existsSync(target)) throw new Error('target already exists');\n        fs.writeFileSync(lock, String(process.pid), { flag: 'wx', mode: 0o600 });\n        if (fs.existsSync(target)) {\n            fs.rmSync(lock, { force: true });\n            throw new Error('target appeared during reservation');\n        }\n        return { target, lock, staging };\n    } catch (error) {\n        throw new CommandExecutionError(`MiniMax music cannot reserve output file ${target}: ${error?.message ?? error}`);\n    }\n}\n\nexport function commitAudioFile(reservation, bytes) {\n    try {\n        fs.writeFileSync(reservation.staging, bytes, { flag: 'wx', mode: 0o600 });\n        // A same-filesystem hard link publishes the complete staging inode and\n        // fails if target already exists on POSIX and Windows alike.\n        fs.linkSync(reservation.staging, reservation.target);\n        cleanupAudioFile(reservation);\n        return reservation.target;\n    } catch (error) {\n        cleanupAudioFile(reservation);\n        throw new CommandExecutionError(`MiniMax music could not atomically write ${reservation.target}: ${error?.message ?? error}`);","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/minimax/utils.js#L174-L210","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (collides when run in parallel)\nminimax music --prompt 'lofi' --output ./out &\nminimax music --prompt 'lofi' --output ./out &\n\n// after (per-job output dir avoids same-second collision)\nminimax music --prompt 'lofi' --output ./out/job-$$_$(date +%s%N)","handlingStrategy":"try-catch","validationCode":"const target = path.join(dir, `${model}-${stamp}.${format}`);\nif (fs.existsSync(target)) throw new Error(`output already exists: ${target}`);\nfs.accessSync(dir, fs.constants.W_OK);","typeGuard":null,"tryCatchPattern":"try {\n  const reservation = reserveAudioFile(dir, model, format);\n  // ... generate and commit\n} catch (e) {\n  if (String(e.message).includes('target appeared during reservation')) {\n    // concurrent run won the race: retry with a fresh timestamp or another dir\n  } else { throw e; }\n}","preventionTips":["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."],"tags":["filesystem","race-condition","toctou","cli"],"backgroundTag":"file-exists-race-condition","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}