material-components/material-components-android · error · IllegalArgumentException

Transient bottom bar must have non-null callback

Error message

Transient bottom bar must have non-null callback

What it means

IllegalArgumentException from the BaseTransientBottomBar constructor when the ContentViewCallback is null. The callback drives the show/hide animations of the content; subclasses like Snackbar supply it automatically, so this throw mainly affects code constructing BaseTransientBottomBar subclasses directly with a null callback.

Source

Thrown at lib/java/com/google/android/material/snackbar/BaseTransientBottomBar.java:361

      @NonNull ViewGroup parent,
      @NonNull View content,
      @NonNull com.google.android.material.snackbar.ContentViewCallback contentViewCallback) {
    this(parent.getContext(), parent, content, contentViewCallback);
  }

  protected BaseTransientBottomBar(
      @NonNull Context context,
      @NonNull ViewGroup parent,
      @NonNull View content,
      @NonNull com.google.android.material.snackbar.ContentViewCallback contentViewCallback) {
    if (parent == null) {
      throw new IllegalArgumentException("Transient bottom bar must have non-null parent");
    }
    if (content == null) {
      throw new IllegalArgumentException("Transient bottom bar must have non-null content");
    }
    if (contentViewCallback == null) {
      throw new IllegalArgumentException("Transient bottom bar must have non-null callback");
    }

    targetParent = parent;
    this.contentViewCallback = contentViewCallback;
    this.context = context;

    ThemeEnforcement.checkAppCompatTheme(context);

    LayoutInflater inflater = LayoutInflater.from(context);
    // Note that for backwards compatibility reasons we inflate a layout that is defined
    // in the extending Snackbar class. This is to prevent breakage of apps that have custom
    // coordinator layout behaviors that depend on that layout.
    view = (SnackbarBaseLayout) inflater.inflate(getSnackbarBaseLayoutResId(), targetParent, false);
    view.setBaseTransientBottomBar(this);
    if (content instanceof SnackbarContentLayout) {
      ((SnackbarContentLayout) content)
          .updateActionTextColorAlphaIfNeeded(view.getActionTextColorAlpha());
      ((SnackbarContentLayout) content).setMaxInlineActionWidth(view.getMaxInlineActionWidth());

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Provide a real ContentViewCallback; if no animation is wanted, implement a no-op callback rather than null.
  2. Reuse Snackbar's BaseCallback-style patterns or copy a minimal no-op implementation.
  3. Null-check constructor arguments in the subclass before delegating to super.

Example fix

// before
new MyTransientBar(parent, content, null); // throws

// after
new MyTransientBar(parent, content, new ContentViewCallback() {
  @Override public void animateContentIn(int delay, int duration) {}
  @Override public void animateContentOut(int delay, int duration) {}
});
Defensive patterns

Strategy: fallback

Validate before calling

ContentViewCallback cb = (callback != null) ? callback : new ContentViewCallback() {
  @Override public void animateContentIn(int delay, int duration) {}
  @Override public void animateContentOut(int delay, int duration) {}
};
new MyTransientBar(parent, content, cb);

Prevention

When it happens

Trigger: Building a custom transient bottom bar and passing null for the ContentViewCallback (e.g. animations deemed unnecessary); DI or reflection paths where the callback parameter was omitted.

Common situations: First-time implementations of custom transients that underestimate the callback's role; refactorings that dropped the callback argument.

Related errors


AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14). Data as JSON: /api/errors/53746e15635438ee. Report an issue: GitHub.