Hi all,
since roughly the last Retool update our workflow that generates MP3 files via the ElevenLabs API and stores them in Retool Storage produces unplayable files. The setup has been running unchanged for months, and files created before the update are fine. I have narrowed it down to the REST block in Workflows and would like to know whether others see the same behaviour.
Setup
-
Workflow, Loop block (
create_audio, execution mode Batched, batch size 5) -
Loop runner: REST query against
https://api.elevenlabs.io/v1/text-to-speech/{voice_id}(POST, headerAccept: audio/mpeg) -
Second Loop block (
save_mp3) with Retool Storage as loop runner, action "Upload file", file content{{ value.base64Data }}, file namepart-<id>.mp3 -
Retool Cloud,
x-retool-api-version: 4.52.0-2338586 (Build 379538)
What happens
The REST block returns the response correctly typed as binary, but the bytes are corrupted. Here is the relevant part of the block output:
json
{
"data": [{
"name": "Xb7hH8MSUJpSbSDYk0k2",
"type": "audio/mpeg",
"sizeBytes": 750534,
"base64Data": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjYwLjE2LjEwMQAAAAAAAAAAAAAA77+977+977+977+9AAAA..."
}],
"metadata": [{
"headers": {
"content-type": ["audio/mpeg"],
"content-length": ["420928"]
},
"status": 200
}]
}
Two things stand out:
-
The upstream response is
content-length: 420928, but Retool reportssizeBytes: 750534- almost twice the size. -
The base64 payload contains the sequence
77+9over and over again, right after the ID3 header where the first MP3 frame sync (FF FB) should be.77+9is base64 forEF BF BD, which is the UTF-8 encoding of U+FFFD (the replacement character).
Both symptoms point to the same root cause: the binary body is being decoded as a UTF-8 string somewhere in the REST block, every byte that is not valid UTF-8 is replaced with U+FFFD, and the result is then re-encoded to bytes and base64. The ID3 tag survives because it is ASCII only, so file still identifies the result as "Audio file with ID3 version 2.4.0", but there is not a single valid MPEG frame left in the file. ffprobe reports Duration: N/A, 0 channels, and browsers show 0:00 / 0:00.
Downloading the same ElevenLabs response with curl gives a valid MP3 with exactly 420928 bytes, so the API side is fine.
Expected behaviour
For a response with content-type: audio/mpeg, base64Data should be the base64 encoding of the raw response bytes, and sizeBytes should match content-length.