{"record":{"id":"ed878c512debc145","repo":"jackwener/OpenCLI","slug":"minimax-music-could-not-atomically-write-reserva","errorCode":null,"errorMessage":"MiniMax music could not atomically write ${reservation.target}: ${error?.message ?? error}","messagePattern":"MiniMax music could not atomically write (.+?): (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/minimax/utils.js","lineNumber":210,"sourceCode":"            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}`);\n    }\n}\n\nexport function cleanupAudioFile(reservation) {\n    if (!reservation) return;\n    fs.rmSync(reservation.staging, { force: true });\n    fs.rmSync(reservation.lock, { force: true });\n}\n","sourceCodeStart":192,"sourceCodeEnd":219,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/minimax/utils.js#L192-L219","documentation":"commitAudioFile writes decoded audio bytes to a private staging file and publishes it atomically via fs.linkSync (hard link staging -> target), which fails if the target already exists. On any failure (staging write error, link error such as EEXIST/EXDEV, disk full) it removes staging and lock files and throws CommandExecutionError 'MiniMax music could not atomically write <target>: <cause>'.","triggerScenarios":"fs.writeFileSync(staging, bytes, {flag:'wx'}) fails (disk full, permission denied), or fs.linkSync(staging, target) fails — most commonly EEXIST because the target appeared between reservation and commit, or EXDEV when staging and target are on different filesystems.","commonSituations":"Disk quota/full volume while writing large WAV audio; another process creating the same target path before commit; output directory on a different mount point so hard links are impossible; antivirus/backup software touching the staging tmp file mid-write.","solutions":["Check free disk space on the output volume (`df -h <dir>`) if the cause is ENOSPC and free space.","If the cause is EEXIST, delete or rename the existing target file and rerun.","If the cause is EXDEV, keep --output on the same filesystem as the temp dir, or fall back to fs.renameSync.","Fix directory write permissions if the cause is EACCES on staging or target creation."],"exampleFix":"// before\nfs.linkSync(reservation.staging, reservation.target); // EXDEV across mounts\n\n// after (rename fallback stays atomic and works when link is unsupported)\ntry { fs.linkSync(reservation.staging, reservation.target); }\ncatch (e) { if (e.code === 'EXDEV') fs.renameSync(reservation.staging, reservation.target); else throw e; }","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\nfunction preflightCommit(target, dir) {\n  fs.accessSync(dir, fs.constants.W_OK);\n  if (fs.existsSync(target)) throw new Error(`target exists: ${target}`);\n  const st = fs.statfsSync(dir);\n  if (st.bavail * st.bsize < 50 * 1024 * 1024) throw new Error('low disk space');\n  if (fs.statfsSync(os.tmpdir()).dev !== st.dev) {\n    console.warn('staging/tmp on different device: fs.linkSync may fail with EXDEV');\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  commitAudioFile(reservation, bytes);\n} catch (e) {\n  if (/atomically write|EEXIST/.test(e.message)) {\n    // target raced: remove or rename existing file, re-reserve, retry once\n  } else if (/ENOSPC/.test(e.message)) {\n    console.error('Free disk space and rerun');\n  } else { throw e; }\n} finally {\n  cleanupAudioFile(reservation); // idempotent; clears staging and lock\n}","preventionTips":["Monitor free disk space before generating large WAV files.","Never create files at the reserved target path while a generation runs.","Keep the output directory on the same filesystem as the temp/staging dir.","Always call cleanupAudioFile after failures to avoid stale locks."],"tags":["filesystem","atomic-write","disk","cli"],"backgroundTag":"atomic-file-write-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}