{"record":{"id":"4502ebdec22ca3e2","repo":"harry0703/MoneyPrinterTurbo","slug":"sonilo-returned-an-invalid-audio-chunk","errorCode":null,"errorMessage":"Sonilo returned an invalid audio chunk","messagePattern":"Sonilo returned an invalid audio chunk","errorType":"exception","errorClass":"SoniloError","httpStatus":null,"severity":"error","filePath":"app/services/sonilo.py","lineNumber":254,"sourceCode":"                title = str(event.get(\"title\") or event.get(\"data\") or \"\")[:200]\n                continue\n            if event_type == \"complete\":\n                completed = True\n                break\n            if event_type != \"audio_chunk\":\n                logger.debug(f\"ignoring unsupported Sonilo event: type={event_type}\")\n                continue\n\n            stream_index = event.get(\"stream_index\", 0)\n            if stream_index != 0:\n                continue\n            encoded_chunk = event.get(\"data\") or event.get(\"audio\")\n            if not isinstance(encoded_chunk, str) or not encoded_chunk:\n                raise SoniloError(\"Sonilo returned an empty audio chunk\")\n            try:\n                chunk = base64.b64decode(encoded_chunk, validate=True)\n            except (binascii.Error, ValueError) as exc:\n                raise SoniloError(\"Sonilo returned an invalid audio chunk\") from exc\n            if not chunk:\n                raise SoniloError(\"Sonilo returned an empty audio chunk\")\n            total_bytes += len(chunk)\n            if total_bytes > MAX_GENERATED_AUDIO_BYTES:\n                raise SoniloError(\"Sonilo audio exceeds the 30 MB limit\")\n            output.write(chunk)\n        output.flush()\n        os.fsync(output.fileno())\n\n    if not completed:\n        raise SoniloError(\"Sonilo stream ended before completion\")\n    if total_bytes <= 0:\n        raise SoniloError(\"Sonilo returned no audio data\")\n    return total_bytes, title\n\n\ndef _request_bgm(video_path: str, output_path: str, prompt: str) -> str:\n    \"\"\"请求配乐并在完整协议及音频校验通过后原子保存。\"\"\"","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/sonilo.py#L236-L272","documentation":"Raised when the base64 payload of an audio chunk fails strict decoding (base64.b64decode with validate=True raises binascii.Error or ValueError). The chunk field was a non-empty string but contains characters outside the base64 alphabet or wrong padding; the data is corrupted or not actually standard base64.","triggerScenarios":"The chunk arrives as URL-safe base64 (dash and underscore instead of plus and slash) while the decoder expects the standard alphabet; padding was stripped by a transport layer; mojibake from a mis-declared charset; the provider switched to base85 or hex encoding.","commonSituations":"Provider changes base64 flavor between API versions; a gateway or middleware re-encodes or mangles the body; proxies applying charset transcoding to the streaming response.","solutions":["Capture the first failing chunk string and test the URL-safe alphabet (altchars) — if that decodes, add URL-safe handling.","Check for transport mangling: compare the chunk length modulo 4 (padding loss) and inspect for injected CRLF sequences.","Review the provider changelog for encoding changes.","If the corruption is network truncation, retry the request."],"exampleFix":"# before\nchunk = base64.b64decode(encoded_chunk, validate=True)\n# after (accept URL-safe alphabet too)\nchunk = base64.b64decode(encoded_chunk.translate(str.maketrans('-_', '+/')), validate=True)","handlingStrategy":"retry","validationCode":"import base64, binascii\n\ndef is_std_base64(s: str) -> bool:\n    try:\n        base64.b64decode(s, validate=True)\n        return True\n    except (binascii.Error, ValueError):\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    audio = request_bgm(video, out, prompt)\nexcept SoniloError as exc:\n    if \"invalid audio chunk\" in str(exc):\n        # encoding drift vs corruption: retry once, then report\n        retry_once_or_report_encoding_issue(exc)\n    raise","preventionTips":["Avoid intermediaries that transcode response bodies (charset rewrites, content optimizers).","If the provider documents URL-safe base64, normalize the alphabet before decoding."],"tags":["sonilo","base64","streaming","encoding"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}