{"record":{"id":"b5fef683236fb0ad","repo":"jackwener/OpenCLI","slug":"minimax-music-returned-data-audio-that-is-not-a-ur","errorCode":null,"errorMessage":"MiniMax music returned data.audio that is not a URL","messagePattern":"MiniMax music returned data\\.audio that is not a URL","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/minimax/utils.js","lineNumber":140,"sourceCode":"}\n\nfunction parseExpectedSize(extraInfo) {\n    if (!extraInfo || typeof extraInfo !== 'object' || Array.isArray(extraInfo)) {\n        throw new CommandExecutionError('MiniMax music returned malformed extra_info');\n    }\n    if (extraInfo.music_size == null) return null;\n    if (!Number.isSafeInteger(extraInfo.music_size) || extraInfo.music_size <= 0) {\n        throw new CommandExecutionError('MiniMax music returned invalid extra_info.music_size');\n    }\n    return extraInfo.music_size;\n}\n\nexport function requireAudioUrl(value) {\n    let url;\n    try {\n        url = new URL(value);\n    } catch {\n        throw new CommandExecutionError('MiniMax music returned data.audio that is not a URL');\n    }\n    if (url.protocol !== 'https:') {\n        throw new CommandExecutionError(`MiniMax music returned a non-HTTPS audio URL (${url.protocol})`);\n    }\n    return url.toString();\n}\n\nexport function decodeAudioHex(value, expectedBytes, format) {\n    if (value.length === 0 || value.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(value)) {\n        throw new CommandExecutionError('MiniMax music returned invalid hexadecimal audio');\n    }\n    const bytes = Buffer.from(value, 'hex');\n    if (expectedBytes != null && bytes.length !== expectedBytes) {\n        throw new CommandExecutionError(`MiniMax music audio size mismatch (expected ${expectedBytes} bytes, got ${bytes.length})`);\n    }\n    if (format === 'wav' && (bytes.length < 12 || bytes.subarray(0, 4).toString('ascii') !== 'RIFF' || bytes.subarray(8, 12).toString('ascii') !== 'WAVE')) {\n        throw new CommandExecutionError('MiniMax music returned bytes that are not a WAV file');\n    }","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/minimax/utils.js#L122-L158","documentation":"requireAudioUrl runs data.audio through new URL() and throws when the value cannot be parsed as a URL at all — meaning the audio field held something else (raw hex, base64, a bare path, or empty string). This guards the URL-based download path from being handed non-URL payloads.","triggerScenarios":"The response's data.audio contains hex-encoded bytes (hex string parses as a URL scheme? no — URL() rejects it), a relative path like /audio/abc.mp3, base64 data, or an empty string; also when the endpoint switched from returning URLs to returning hex and the caller used the wrong handler.","commonSituations":"Calling requireAudioUrl on a response from an endpoint that returns hex audio instead of a URL; MiniMax returning a protocol-relative or relative URL; empty audio field slipping past an earlier check.","solutions":["Check whether data.audio looks like hex (matches /^[0-9a-f]+$/i) and use decodeAudioHex instead of requireAudioUrl","If it's a relative path, prefix the MiniMax CDN base URL before parsing","Log the value to confirm what form the audio actually takes","Ensure you call the right handler for your endpoint variant (URL vs hex payload)"],"exampleFix":"// before\nconst url = requireAudioUrl(data.audio);\n// after\nif (/^[0-9a-f]+$/.test(data.audio)) {\n  const bytes = decodeAudioHex(data.audio, expectedBytes, format);\n} else {\n  const url = requireAudioUrl(data.audio.startsWith('/') ? BASE + data.audio : data.audio);\n}","handlingStrategy":"type-guard","validationCode":"function isHttpUrl(v) {\n  try { const u = new URL(v); return u.protocol === 'http:' || u.protocol === 'https:'; }\n  catch { return false; }\n}\nif (!isHttpUrl(payload?.data?.audio)) {\n  // route to hex/base64 decode path instead\n}","typeGuard":"function isAbsoluteUrl(v) {\n  if (typeof v !== 'string') return false;\n  try { new URL(v); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const url = requireAudioUrl(data.audio);\n} catch (e) {\n  if (/not a URL/.test(e.message)) {\n    // data.audio is likely hex or base64 — decode instead\n    const bytes = decodeAudioHex(data.audio, expectedBytes, format);\n  } else throw e;\n}","preventionTips":["Detect payload form (URL vs hex) before choosing the handler","Prefix relative paths with the MiniMax CDN base URL","Validate response shape with fixtures from the live endpoint","Keep URL-handling and hex-handling paths clearly separated in your code"],"tags":["minimax","music","url-parsing","audio"],"backgroundTag":"invalid-url-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}