{"id":"598defaa5e8212b4","repo":"apache/kafka","slug":"unsupported-subscription-version","errorCode":null,"errorMessage":"Unsupported subscription version: {}","messagePattern":"Unsupported subscription version: (.+?)","errorType":"exception","errorClass":"SchemaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerProtocol.java","lineNumber":217,"sourceCode":"        final ByteBuffer buffer,\n        short version\n    ) {\n        version = checkAssignmentVersion(version);\n\n        try {\n            return new ConsumerProtocolAssignment(new ByteBufferAccessor(buffer), version);\n        } catch (RuntimeException e) {\n            throw new SchemaException(\"Malformed consumer protocol assignment\", e);\n        }\n    }\n\n    public static ConsumerProtocolAssignment deserializeConsumerProtocolAssignment(final ByteBuffer buffer) {\n        return deserializeConsumerProtocolAssignment(buffer, deserializeVersion(buffer));\n    }\n\n    private static short checkSubscriptionVersion(final short version) {\n        if (version < ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION)\n            throw new SchemaException(\"Unsupported subscription version: \" + version);\n        else if (version > ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION)\n            return ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION;\n        else\n            return version;\n    }\n\n    private static short checkAssignmentVersion(final short version) {\n        if (version < ConsumerProtocolAssignment.LOWEST_SUPPORTED_VERSION)\n            throw new SchemaException(\"Unsupported assignment version: \" + version);\n        else if (version > ConsumerProtocolAssignment.HIGHEST_SUPPORTED_VERSION)\n            return ConsumerProtocolAssignment.HIGHEST_SUPPORTED_VERSION;\n        else\n            return version;\n    }\n}\n","sourceCodeStart":199,"sourceCodeEnd":233,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerProtocol.java#L199-L233","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log the offending version value to confirm whether it is a real legacy version or a parsing corruption (0 typically signals corruption).","If legitimately reading legacy data, downgrade the reader to a Kafka client version whose LOWEST_SUPPORTED_VERSION covers it.","If the version came from deserializeVersion, validate buffer length/contents (see Buffer underflow error) before trusting the header.","Regenerate the subscription payload via ConsumerProtocol.serializeSubscription (no explicit version) so it uses HIGHEST_SUPPORTED_VERSION."],"exampleFix":"// before\nConsumerProtocol.serializeSubscription(sub, (short) 0);\n\n// after\nConsumerProtocol.serializeSubscription(sub); // uses HIGHEST_SUPPORTED_VERSION","handlingStrategy":"validation","validationCode":"// checkSubscriptionVersion rejects versions below LOWEST_SUPPORTED_VERSION.\n// Validate (and optionally clamp) the version before any (de)serialize call.\nimport org.apache.kafka.common.message.ConsumerProtocolSubscription;\n\nstatic short ensureSupportedSubscriptionVersion(short version) {\n    if (version < ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION)\n        throw new IllegalArgumentException(\n            \"subscription version \" + version + \" below lowest supported \"\n            + ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION);\n    return (short) Math.min(version, ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION);\n}","typeGuard":"// Narrow a candidate version to the supported subscription-protocol range.\nstatic boolean isSupportedSubscriptionVersion(short v) {\n    return v >= ConsumerProtocolSubscription.LOWEST_SUPPORTED_VERSION\n        && v <= ConsumerProtocolSubscription.HIGHEST_SUPPORTED_VERSION;\n}","tryCatchPattern":"try {\n    ConsumerProtocol.serializeSubscription(subscription, version);\n} catch (org.apache.kafka.common.protocol.types.SchemaException e) {\n    // Reached only if version < LOWEST_SUPPORTED_VERSION — indicates stale client\n    // reading bytes written by an even older client, or a hand-crafted version field.\n    log.error(\"Unsupported consumer protocol subscription version\", e);\n    throw e;\n}","preventionTips":["Do not pin the consumer protocol version by hand; let ConsumerProtocol.serializeSubscription() use HIGHEST_SUPPORTED_VERSION by default.","Upgrade all members of a consumer group together so none tries to decode bytes from a removed legacy version.","If you must interoperate with a legacy client, negotiate the lowest version both sides support before serializing."],"tags":["consumer","protocol","version","schema","subscription"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}