google/ExoPlayer · error · AudioSink.ConfigurationException

Unable to configure passthrough for: %s

Error message

Unable to configure passthrough for: %s

What it means

When DefaultAudioSink is configured to pass the compressed bitstream straight to the output device (OUTPUT_MODE_PASSTHROUGH), it asks the device's AudioCapabilities for a (encoding, channelConfig) pair the output can actually decode. If getEncodingAndChannelConfigForPassthrough returns null — the device/TV/receiver does not advertise support for that encoding/channel combination — a ConfigurationException('Unable to configure passthrough for: <format>') is thrown from AudioSink.configure.

Source

Thrown at library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java:715

      // Audio processing is not supported in offload or passthrough mode.
      audioProcessingPipeline = new AudioProcessingPipeline(ImmutableList.of());
      inputPcmFrameSize = C.LENGTH_UNSET;
      outputSampleRate = inputFormat.sampleRate;
      outputPcmFrameSize = C.LENGTH_UNSET;
      if (useOffloadedPlayback(inputFormat, audioAttributes)) {
        outputMode = OUTPUT_MODE_OFFLOAD;
        outputEncoding =
            MimeTypes.getEncoding(checkNotNull(inputFormat.sampleMimeType), inputFormat.codecs);
        outputChannelConfig = Util.getAudioTrackChannelConfig(inputFormat.channelCount);
        // Offload requires AudioTrack playback parameters to apply speed changes quickly.
        enableAudioTrackPlaybackParams = true;
      } else {
        outputMode = OUTPUT_MODE_PASSTHROUGH;
        @Nullable
        Pair<Integer, Integer> encodingAndChannelConfig =
            getAudioCapabilities().getEncodingAndChannelConfigForPassthrough(inputFormat);
        if (encodingAndChannelConfig == null) {
          throw new ConfigurationException(
              "Unable to configure passthrough for: " + inputFormat, inputFormat);
        }
        outputEncoding = encodingAndChannelConfig.first;
        outputChannelConfig = encodingAndChannelConfig.second;
        // Passthrough only supports AudioTrack playback parameters, but we only enable it this was
        // specifically requested by the app.
        enableAudioTrackPlaybackParams = preferAudioTrackPlaybackParams;
      }
    }

    if (outputEncoding == C.ENCODING_INVALID) {
      throw new ConfigurationException(
          "Invalid output encoding (mode=" + outputMode + ") for: " + inputFormat, inputFormat);
    }
    if (outputChannelConfig == AudioFormat.CHANNEL_INVALID) {
      throw new ConfigurationException(
          "Invalid output channel config (mode=" + outputMode + ") for: " + inputFormat,
          inputFormat);

View on GitHub (pinned to dd430f7053)

Solutions

  1. Play in PCM decode mode instead: don't force passthrough — let DefaultTrackSelector choose decodable tracks (disable the passthrough flag / Map<String, String> override).
  2. Advertise capabilities explicitly if the environment is known: DefaultAudioSink.Builder.setAudioCapabilities(AudioCapabilities.EXTERNAL_SURROUND) or construct from AudioManager settings.
  3. Include a PCM fallback variant in your HLS/DASH manifest and let ExoPlayer's track selection fall back when passthrough fails (set enabled decoders via RenderersFactory with enableDecoderFallback).
  4. Catch ConfigurationException around playback initiation and retry after disabling passthrough for that item.

Example fix

// before — force passthrough for everything
trackSelector.setParameters(
    new DefaultTrackSelector.Parameters.Builder(ctx)
        .setOverrideDisableAudioRenderersIfDecoderInitFails(false)
        .build()); // + custom selector preferring passthrough

// after — allow decode fallback when the sink cannot passthrough
trackSelector.setParameters(
    new DefaultTrackSelector.Parameters.Builder(ctx)
        .setExceedAudioConstraintsIfNecessary(true)
        .build());
// DefaultRenderersFactory
new DefaultRenderersFactory(ctx).setEnableDecoderFallback(true);
Defensive patterns

Strategy: fallback

Validate before calling

AudioCapabilities caps = DefaultAudioSink.getAudioCapabilities(context);
// null here => device cannot passthrough this format
if (caps.getEncodingAndChannelConfigForPassthrough(format) == null) {
  selectPcmPlayback();
}

Try / catch

try {
  player.setMediaItem(passthroughItem);
  player.prepare();
} catch (PlaybackException e) {
  if (e.getErrorCode()
      == PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED) {
    switchToPcmAndRetry(passthroughItem);
  }
}

Prevention

When it happens

Trigger: Playing AC-3/E-AC-3/DTS/TrueHD etc. with passthrough enabled (DefaultAudioSink offload or the MediaCodec selector choosing a passthrough decoder) on a device whose AudioManager reports no matching surrogate encoding/channel layout — e.g. sending 6-channel E-AC-3 to a TV that only accepts 2-channel AAC.

Common situations: Android TV apps assuming receivers support AC-3; HDMI chain (dongle → AVR → TV) where the reported capabilities reflect the final sink; USB/headphone output advertising no compressed encodings; emulator images with no passthrough capability; channel-count mismatch between stream and device-reported max.

Related errors


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/2473b33bbe10aea9. Report an issue: GitHub.