sipeed/picoclaw · error

failed to decode audio data: %w

Error message

failed to decode audio data: %w

What it means

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.

Source

Thrown at pkg/audio/tts/mimo_tts.go:158

				Audio struct {
					Data string `json:"data"`
				} `json:"audio"`
			} `json:"message"`
		} `json:"choices"`
	}

	err = json.Unmarshal(body, &payload)
	if err != nil {
		return nil, fmt.Errorf("failed to decode response: %w", err)
	}

	if len(payload.Choices) == 0 || payload.Choices[0].Message.Audio.Data == "" {
		return nil, fmt.Errorf("invalid TTS response: missing audio data")
	}

	audioBytes, err := base64.StdEncoding.DecodeString(payload.Choices[0].Message.Audio.Data)
	if err != nil {
		return nil, fmt.Errorf("failed to decode audio data: %w", err)
	}

	return io.NopCloser(bytes.NewReader(audioBytes)), nil
}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Log a short prefix/suffix sample of the data field to spot prefixes or line wrapping
  2. Strip any 'data:...;base64,' prefix and all whitespace before decoding
  3. Try RawStdEncoding and URLEncoding variants as a compatibility shim
  4. If it persists, the API contract changed — update the provider or report upstream

Example fix

// before
b, err := base64.StdEncoding.DecodeString(data)
// after
clean := strings.Map(func(r rune) rune {
    if r == ' ' || r == '\t' || r == '\r' || r == '\n' {
        return -1
    }
    return r
}, data)
b, err := base64.StdEncoding.DecodeString(clean)
if err != nil {
    b, err = base64.RawStdEncoding.DecodeString(clean)
}
Defensive patterns

Strategy: try-catch

Type guard

func isBase64Corrupt(err error) bool {
    var cie base64.CorruptInputError
    return errors.As(err, &cie)
}

Try / catch

if err != nil && isBase64Corrupt(err) {
    // provider encoding drift: re-synthesize once; if it repeats, the API changed —
    // strip data-URI prefixes / whitespace or try alternate encodings, then report upstream
}

Prevention

When it happens

Trigger: 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.

Common situations: API version changes on api.xiaomimimo.com; intermediaries that mangle very long strings.

Understand the failure class

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/cdcf1d66fd4f215c. Report an issue: GitHub.