{"record":{"id":"a339bba774b02d6f","repo":"jackwener/OpenCLI","slug":"unsupported-home-directory-path-raw","errorCode":null,"errorMessage":"Unsupported home-directory path: ${raw}","messagePattern":"Unsupported home-directory path: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/minimax/utils.js","lineNumber":175,"sourceCode":"        throw new CommandExecutionError('MiniMax music returned bytes that are not a WAV file');\n    }\n    if (format === 'mp3' && !isMp3(bytes)) {\n        throw new CommandExecutionError('MiniMax music returned bytes that are not an MP3 file');\n    }\n    return bytes;\n}\n\nfunction isMp3(bytes) {\n    return bytes.length >= 3 && bytes.subarray(0, 3).toString('ascii') === 'ID3'\n        || bytes.length >= 2 && bytes[0] === 0xff && (bytes[1] & 0xe0) === 0xe0;\n}\n\nexport function resolveOutputDir(value) {\n    const raw = String(value ?? '').trim();\n    if (!raw) return path.join(os.homedir(), 'Music', 'minimax');\n    if (raw === '~') return os.homedir();\n    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        }","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/minimax/utils.js#L157-L193","documentation":"resolveOutputDir expands a user-supplied output directory value, accepting '~' or '~/...' forms that map to the OS home directory. A bare '~'-prefixed path like '~user/music' or '~foo' is not supported, so the library throws ArgumentError to refuse ambiguous home-directory syntax rather than guessing the target.","triggerScenarios":"Passing an output-directory option whose trimmed string starts with '~' but is neither exactly '~' nor starts with '~/': e.g. '~user', '~music', '~/', wait — '~/' matches the handled case, so effectively '~name' style paths.","commonSituations":"Users copying shell-idiom paths like '~otheruser/Music' into CLI config/env; typos where '~/' was written as '~'; docs showing '~name' expansion that Node's os.homedir() cannot resolve.","solutions":["Replace the value with an absolute path, e.g. /home/otheruser/Music or /Users/me/Music","Use '~' or '~/...' forms only, which the library expands via os.homedir()","Set an env var or CLI flag with the resolved absolute path instead of relying on shell expansion","If you need ~user expansion, resolve it in your own code (e.g. via getpwnam/passwd lookup) before passing it in"],"exampleFix":"// before\nresolveOutputDir('~music');            // throws ArgumentError\n// after\nresolveOutputDir(path.join(os.homedir(), 'Music'));\n// or\nresolveOutputDir('~/Music');","handlingStrategy":"validation","validationCode":"function isValidOutputDir(value) {\n    const raw = String(value ?? '').trim();\n    if (!raw) return true;                 // falls back to default\n    if (raw === '~' || raw.startsWith('~/')) return true;\n    if (raw.startsWith('~')) return false; // would throw ArgumentError\n    return true;\n}\n// if (!isValidOutputDir(cfg.outputDir)) cfg.outputDir = cfg.outputDir.replace(/^~[^/]*/, os.homedir());","typeGuard":null,"tryCatchPattern":"try {\n    const dir = resolveOutputDir(opts.outputDir);\n} catch (e) {\n    if (e instanceof ArgumentError && String(e.message).includes('Unsupported home-directory path')) {\n        const dir = resolveOutputDir(opts.outputDir.replace(/^~(?![/])/, os.homedir() + '/'));\n    } else throw e;\n}","preventionTips":["Only pass '~' or '~/...' home paths, or fully-resolved absolute paths","Expand ~user syntax yourself before calling resolveOutputDir","Validate config values at startup with a dry-run of resolveOutputDir","Document accepted forms for users editing config/env"],"tags":["minimax","path","argument-validation","tilde-expansion"],"backgroundTag":"unsupported-path-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}