apache/kafka · error · ConfigException

Invalid value null for configuration value.deserializer: mus

Error message

Invalid value null for configuration value.deserializer: must be non-null.

What it means

Thrown by ConsumerConfig.appendDeserializerToConfig when neither a value Deserializer instance nor the value.deserializer configuration property is provided. Symmetric to the key.deserializer check; every KafkaConsumer requires a value deserializer to materialize record values. It is a ConfigException raised during KafkaConsumer initialization.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerConfig.java:802

            String groupInstanceIdPart = groupInstanceId != null ? groupInstanceId : CONSUMER_CLIENT_ID_SEQUENCE.getAndIncrement() + "";
            String generatedClientId = String.format("consumer-%s-%s", groupId, groupInstanceIdPart);
            configs.put(CLIENT_ID_CONFIG, generatedClientId);
        }
    }

    public static Map<String, Object> appendDeserializerToConfig(Map<String, Object> configs,
                                                                 Deserializer<?> keyDeserializer,
                                                                 Deserializer<?> valueDeserializer) {
        // validate deserializer configuration, if the passed deserializer instance is null, the user must explicitly set a valid deserializer configuration value
        Map<String, Object> newConfigs = new HashMap<>(configs);
        if (keyDeserializer != null)
            newConfigs.put(KEY_DESERIALIZER_CLASS_CONFIG, keyDeserializer.getClass());
        else if (newConfigs.get(KEY_DESERIALIZER_CLASS_CONFIG) == null)
            throw new ConfigException(KEY_DESERIALIZER_CLASS_CONFIG, null, "must be non-null.");
        if (valueDeserializer != null)
            newConfigs.put(VALUE_DESERIALIZER_CLASS_CONFIG, valueDeserializer.getClass());
        else if (newConfigs.get(VALUE_DESERIALIZER_CLASS_CONFIG) == null)
            throw new ConfigException(VALUE_DESERIALIZER_CLASS_CONFIG, null, "must be non-null.");
        return newConfigs;
    }

    private void maybeOverrideEnableAutoCommit(Map<String, Object> configs) {
        Optional<String> groupId = Optional.ofNullable(getString(CommonClientConfigs.GROUP_ID_CONFIG));
        Map<String, Object> originals = originals();
        boolean enableAutoCommit = originals.containsKey(ENABLE_AUTO_COMMIT_CONFIG) ? getBoolean(ENABLE_AUTO_COMMIT_CONFIG) : false;
        if (groupId.isEmpty()) { // overwrite in case of default group id where the config is not explicitly provided
            if (!originals.containsKey(ENABLE_AUTO_COMMIT_CONFIG)) {
                configs.put(ENABLE_AUTO_COMMIT_CONFIG, false);
            } else if (enableAutoCommit) {
                throw new InvalidConfigurationException(ENABLE_AUTO_COMMIT_CONFIG + " cannot be set to true when default group id (null) is used.");
            }
        }
    }

    protected void checkUnsupportedConfigsPostProcess() {
        String groupProtocol = getString(GROUP_PROTOCOL_CONFIG);

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Set props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); before constructing the consumer.
  2. Or pass a non-null value Deserializer instance to the KafkaConsumer(Map, Deserializer, Deserializer) constructor.
  3. Validate config keys at startup to catch typos like value.deserializer.class.
  4. If values are intentionally unused, still provide a ByteArrayDeserializer for the value.

Example fix

// before
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
new KafkaConsumer<>(props); // throws: value.deserializer null

// after
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
new KafkaConsumer<>(props);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure value.deserializer is set before constructing the consumer:
Properties props = new Properties();
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
if (props.get(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG) == null && valueDeserializer == null) {
    throw new ConfigException(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, null, "must be non-null");
}

Type guard

static boolean hasValueDeserializer(Map<String, Object> configs, Deserializer<?> instance) {
    return instance != null || configs.get(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG) != null;
}

Try / catch

try {
    new KafkaConsumer<>(props);
} catch (ConfigException e) {
    if (e.getMessage().contains("value.deserializer")) {
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        new KafkaConsumer<>(props);
    } else throw e;
}

Prevention

When it happens

Trigger: new KafkaConsumer<>(props) (or KafkaConsumer(Map, Deserializer, Deserializer) with valueDeserializer=null) where props does not contain value.deserializer, or where value.deserializer is explicitly null.

Common situations: Forgetting value.deserializer when constructing the consumer; passing a non-null key Deserializer but null value Deserializer to the typed constructor; typo in property name (value.deserializer.class); config-loading bug that omits the value deserializer entry.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/76cfb7030400a568.json. Report an issue: GitHub.