yuliskov/SmartTube · error · IllegalArgumentException

ContentChecker cannot be null when using custom content type

Error message

ContentChecker cannot be null when using custom content types!

What it means

When a message implements MessageContentType and at least one custom content type is registered, getContentViewType must ask the ContentChecker which type the message carries; if the checker field is null at that moment it throws IllegalArgumentException. registerContentType assigns the checker, but its @NonNull is annotation-only, so a null passed at registration compiles fine and detonates later at layout time when the first such message is measured.

Source

Thrown at chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java:665

        } catch (Exception e) {
            throw new UnsupportedOperationException("Somehow we couldn't create the ViewHolder for message. Please, report this issue on GitHub with full stacktrace in description.", e);
        }
    }

    @SuppressWarnings("unchecked")
    private short getContentViewType(IMessage message) {
        if (message instanceof MessageContentType.Image
                && ((MessageContentType.Image) message).getImageUrl() != null) {
            return VIEW_TYPE_IMAGE_MESSAGE;
        }

        // other default types will be here

        if (message instanceof MessageContentType) {
            for (int i = 0; i < customContentTypes.size(); i++) {
                ContentTypeConfig config = customContentTypes.get(i);
                if (contentChecker == null) {
                    throw new IllegalArgumentException("ContentChecker cannot be null when using custom content types!");
                }
                boolean hasContent = contentChecker.hasContentFor(message, config.type);
                if (hasContent) return config.type;
            }
        }

        return VIEW_TYPE_TEXT_MESSAGE;
    }

    /*
     * HOLDERS
     * */

    /**
     * The base class for view holders for incoming and outcoming message.
     * You can extend it to create your own holder in conjuction with custom layout or even using default layout.
     */
    public static abstract class BaseMessageViewHolder<MESSAGE extends IMessage> extends ViewHolder<MESSAGE> {

View on GitHub (pinned to 3de8d90593)

Solutions

  1. Pass a real ContentChecker to every registerContentType call, e.g. (message, type) -> message instanceof MyContentMsg
  2. If messages only need text/image rendering, do not implement MessageContentType on the model class
  3. Assert non-null at registration (Objects.requireNonNull) so failure happens next to the buggy call, not during layout

Example fix

// before
holders.registerContentType((byte) 1, InVH.class, R.layout.in, OutVH.class, R.layout.out, null);

// after
holders.registerContentType((byte) 1, InVH.class, R.layout.in, OutVH.class, R.layout.out,
        (message, type) -> message instanceof MyContentMsg);
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(checker, "ContentChecker is required when registering content types");
holders.registerContentType(type, inHolder, inLayout, outHolder, outLayout, checker);

Prevention

When it happens

Trigger: Calling any registerContentType(...) overload with a null ContentChecker and later adding a message whose class implements MessageContentType; reaching getContentViewType's loop with customContentTypes non-empty and contentChecker never assigned.

Common situations: Kotlin callers passing a nullable checker through a platform type without a compile error; trimming sample code and dropping the checker argument; adding MessageContentType to the message model while intending to keep only built-in text/image rendering.

Related errors


AI-assisted analysis of yuliskov/SmartTube@3de8d90593 (2026-08-22). Data as JSON: /api/errors/3760f31316d78ccd. Report an issue: GitHub.