{"record":{"id":"cdcf1d66fd4f215c","repo":"sipeed/picoclaw","slug":"failed-to-decode-audio-data-w","errorCode":null,"errorMessage":"failed to decode audio data: %w","messagePattern":"failed to decode audio data: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/audio/tts/mimo_tts.go","lineNumber":158,"sourceCode":"\t\t\t\tAudio struct {\n\t\t\t\t\tData string `json:\"data\"`\n\t\t\t\t} `json:\"audio\"`\n\t\t\t} `json:\"message\"`\n\t\t} `json:\"choices\"`\n\t}\n\n\terr = json.Unmarshal(body, &payload)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode response: %w\", err)\n\t}\n\n\tif len(payload.Choices) == 0 || payload.Choices[0].Message.Audio.Data == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid TTS response: missing audio data\")\n\t}\n\n\taudioBytes, err := base64.StdEncoding.DecodeString(payload.Choices[0].Message.Audio.Data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode audio data: %w\", err)\n\t}\n\n\treturn io.NopCloser(bytes.NewReader(audioBytes)), nil\n}\n","sourceCodeStart":140,"sourceCodeEnd":163,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/audio/tts/mimo_tts.go#L140-L163","documentation":"Returned when choices[0].message.audio.data is present but is not decodable with base64.StdEncoding — the field contains whitespace or line wraps, uses URL-safe base64 ('-'/'_' instead of '+'/'/'), has missing or wrong padding, or is a data-URI ('data:audio/mp3;base64,...') instead of raw base64.","triggerScenarios":"Provider switches to URL-safe or unpadded base64; a gateway re-encodes or wraps long lines; the API starts prefixing a data-URI to the payload.","commonSituations":"API version changes on api.xiaomimimo.com; intermediaries that mangle very long strings.","solutions":["Log a short prefix/suffix sample of the data field to spot prefixes or line wrapping","Strip any 'data:...;base64,' prefix and all whitespace before decoding","Try RawStdEncoding and URLEncoding variants as a compatibility shim","If it persists, the API contract changed — update the provider or report upstream"],"exampleFix":"// before\nb, err := base64.StdEncoding.DecodeString(data)\n// after\nclean := strings.Map(func(r rune) rune {\n    if r == ' ' || r == '\\t' || r == '\\r' || r == '\\n' {\n        return -1\n    }\n    return r\n}, data)\nb, err := base64.StdEncoding.DecodeString(clean)\nif err != nil {\n    b, err = base64.RawStdEncoding.DecodeString(clean)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isBase64Corrupt(err error) bool {\n    var cie base64.CorruptInputError\n    return errors.As(err, &cie)\n}","tryCatchPattern":"if err != nil && isBase64Corrupt(err) {\n    // provider encoding drift: re-synthesize once; if it repeats, the API changed —\n    // strip data-URI prefixes / whitespace or try alternate encodings, then report upstream\n}","preventionTips":["Keep the mimo provider version current; encoding fixes land there","Capture a prefix/suffix sample of the data field when this fires","Prefer the openai-tts provider (raw byte stream) when mimo encoding is unstable"],"tags":["base64","encoding","tts","mimo"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}