google/ExoPlayer · error · FlacDecoderException
Failed to decode StreamInfo
Error message
Failed to decode StreamInfo
What it means
FlacDecoderException wrapping a ParserException thrown when decoderJni.decodeStreamMetadata() cannot parse the bytes set from initializationData[0] as a FLAC STREAMINFO block. Unlike the length check, this means one entry existed but its contents are not a valid stream-info header (wrong bytes, wrong offset, or corrupt header).
Source
Thrown at extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoder.java:75
* which is the flac file header.
* @throws FlacDecoderException Thrown if an exception occurs when initializing the decoder.
*/
public FlacDecoder(
int numInputBuffers,
int numOutputBuffers,
int maxInputBufferSize,
List<byte[]> initializationData)
throws FlacDecoderException {
super(new DecoderInputBuffer[numInputBuffers], new SimpleDecoderOutputBuffer[numOutputBuffers]);
if (initializationData.size() != 1) {
throw new FlacDecoderException("Initialization data must be of length 1");
}
decoderJni = new FlacDecoderJni();
decoderJni.setData(ByteBuffer.wrap(initializationData.get(0)));
try {
streamMetadata = decoderJni.decodeStreamMetadata();
} catch (ParserException e) {
throw new FlacDecoderException("Failed to decode StreamInfo", e);
} catch (IOException e) {
// Never happens.
throw new IllegalStateException(e);
}
int initialInputBufferSize =
maxInputBufferSize != Format.NO_VALUE ? maxInputBufferSize : streamMetadata.maxFrameSize;
setInitialInputBufferSize(initialInputBufferSize);
}
@Override
public String getName() {
return "libflac";
}
@Override
protected DecoderInputBuffer createInputBuffer() {
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);View on GitHub (pinned to dd430f7053)
Solutions
- Verify initializationData[0] is exactly the STREAMINFO block: expect 34 bytes starting after the 'fLaC' magic with block header 0x00 (last-block=0, type=0)
- Re-download or re-mux the source file; validate it with 'flac -t' or ffprobe outside the app
- If writing a custom extractor, use FlacConstants and the library's own FrameReader/metadata parsing rather than slicing manually
- Catch FlacDecoderException at renderer construction and surface a 'corrupt file' message or fall back to platform decoding
Example fix
// before: passing the whole file header (magic + block header included)
List<byte[]> init = Collections.singletonList(first38Bytes);
new FlacDecoder(numIn, numOut, maxIn, init); // ParserException: bad StreamInfo
// after: pass only the 34-byte STREAMINFO payload
List<byte[]> init = Collections.singletonList(
Arrays.copyOfRange(header, 4 /* magic */ + 4 /* block header */, 4 + 4 + 34));
new FlacDecoder(numIn, numOut, maxIn, init); Defensive patterns
Strategy: try-catch
Validate before calling
boolean looksLikeStreamInfo(byte[] block) {
return block != null && block.length == 34
&& block[0] != 0; // sampleRate bits (top 20 bits) must be non-zero for real STREAMINFO
}
if (!looksLikeStreamInfo(format.initializationData.get(0))) {
// header bytes are wrong/corrupt: fail with a clear message before decoder init
} Try / catch
try {
decoder = new FlacDecoder(numIn, numOut, maxIn, format.initializationData);
} catch (FlacDecoderException e) {
if (e.getMessage() != null && e.getMessage().contains("StreamInfo")) {
// header block invalid: mark source as corrupt and skip / re-download
markSourceCorrupt(uri);
} else {
throw e;
}
} Prevention
- Pass exactly the 34-byte STREAMINFO payload — never the 'fLaC' magic or the 4-byte block header
- Validate downloaded FLAC files (ffprobe / flac -t) in your ingest pipeline
- Surface ParserException-based failures as 'corrupt file' to users instead of generic decode errors
When it happens
Trigger: initializationData[0] contains bytes that are not the 34-byte STREAMINFO block (e.g. an ID3 tag remnant, the whole file header including the magic, or a partial read); truncated FLAC file; header bytes byte-swapped or re-encoded by an upstream transform.
Common situations: Corrupt downloads; FLAC files with non-standard prepended metadata; custom extractors passing the wrong slice of the header; files that fail sniffing and get misparsed as FLAC.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Initialization data must be of length 1
- Could not delete the previous export output file
- Could not create the export output file
- Failed to load MediaPipeShaderProgram
- Unexpected color filter ${colorFilterSelection}
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/6f31c61849c23744.
Report an issue: GitHub.