apache/kafka · error · SchemaException

Unsupported subscription version: {}

Error message

Unsupported subscription version: {}

What it means

Thrown by ConsumerProtocol.checkSubscriptionVersion() when the supplied subscription version is below ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION. Kafka only guarantees backward compatibility down to LOWEST_SUPPORTED_VERSION; anything older is rejected outright. Versions above HIGHEST_SUPPORTED_VERSION are silently capped (forward-compatibility), so this exception only fires for too-old versions.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerProtocol.java:217

        final ByteBuffer buffer,
        short version
    ) {
        version = checkAssignmentVersion(version);

        try {
            return new ConsumerProtocolAssignment(new ByteBufferAccessor(buffer), version);
        } catch (RuntimeException e) {
            throw new SchemaException("Malformed consumer protocol assignment", e);
        }
    }

    public static ConsumerProtocolAssignment deserializeConsumerProtocolAssignment(final ByteBuffer buffer) {
        return deserializeConsumerProtocolAssignment(buffer, deserializeVersion(buffer));
    }

    private static short checkSubscriptionVersion(final short version) {
        if (version < ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION)
            throw new SchemaException("Unsupported subscription version: " + version);
        else if (version > ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION)
            return ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION;
        else
            return version;
    }

    private static short checkAssignmentVersion(final short version) {
        if (version < ConsumerProtocolAssignment.LOWEST_SUPPORTED_VERSION)
            throw new SchemaException("Unsupported assignment version: " + version);
        else if (version > ConsumerProtocolAssignment.HIGHEST_SUPPORTED_VERSION)
            return ConsumerProtocolAssignment.HIGHEST_SUPPORTED_VERSION;
        else
            return version;
    }
}

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Log the offending version value to confirm whether it is a real legacy version or a parsing corruption (0 typically signals corruption).
  2. If legitimately reading legacy data, downgrade the reader to a Kafka client version whose LOWEST_SUPPORTED_VERSION covers it.
  3. If the version came from deserializeVersion, validate buffer length/contents (see Buffer underflow error) before trusting the header.
  4. Regenerate the subscription payload via ConsumerProtocol.serializeSubscription (no explicit version) so it uses HIGHEST_SUPPORTED_VERSION.

Example fix

// before
ConsumerProtocol.serializeSubscription(sub, (short) 0);

// after
ConsumerProtocol.serializeSubscription(sub); // uses HIGHEST_SUPPORTED_VERSION
Defensive patterns

Strategy: validation

Validate before calling

// checkSubscriptionVersion rejects versions below LOWEST_SUPPORTED_VERSION.
// Validate (and optionally clamp) the version before any (de)serialize call.
import org.apache.kafka.common.message.ConsumerProtocolSubscription;

static short ensureSupportedSubscriptionVersion(short version) {
    if (version < ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION)
        throw new IllegalArgumentException(
            "subscription version " + version + " below lowest supported "
            + ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION);
    return (short) Math.min(version, ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION);
}

Type guard

// Narrow a candidate version to the supported subscription-protocol range.
static boolean isSupportedSubscriptionVersion(short v) {
    return v >= ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION
        && v <= ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION;
}

Try / catch

try {
    ConsumerProtocol.serializeSubscription(subscription, version);
} catch (org.apache.kafka.common.protocol.types.SchemaException e) {
    // Reached only if version < LOWEST_SUPPORTED_VERSION — indicates stale client
    // reading bytes written by an even older client, or a hand-crafted version field.
    log.error("Unsupported consumer protocol subscription version", e);
    throw e;
}

Prevention

When it happens

Trigger: Calling ConsumerProtocol.serializeSubscription or deserializeSubscription/deserializeConsumerProtocolSubscription with an explicit version argument less than LOWEST_SUPPORTED_VERSION (typically negative numbers or 0). Usually arises when a version short is read from a malformed or zeroed header byte, or when a custom caller passes a hardcoded legacy version.

Common situations: A corrupted version prefix (all-zero bytes deserialize as version 0); custom test fixtures passing version 0 or -1; an old snapshot replayed against a client whose LOWEST_SUPPORTED_VERSION has moved up after a Kafka release.

Related errors


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