{"id":"025083d2f8df8830","repo":"apache/kafka","slug":"get-fenced-exception-for-group-instance-id-cur","errorCode":null,"errorMessage":"Get fenced exception for group.instance.id {}, current member.id is {}","messagePattern":"Get fenced exception for group\\.instance\\.id (.+?), current member\\.id is (.+?)","errorType":"exception","errorClass":"FencedInstanceIdException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java","lineNumber":1039,"sourceCode":"        client.disableWakeups();\n        try {\n            maybeAutoCommitOffsetsSync(timer);\n            while (pendingAsyncCommits.get() > 0 && timer.notExpired()) {\n                ensureCoordinatorReady(timer);\n                client.poll(timer);\n                invokeCompletedOffsetCommitCallbacks();\n            }\n        } finally {\n            super.close(timer, membershipOperation);\n            Utils.closeQuietly(coordinatorMetrics, \"consumer coordinator metrics\");\n            Utils.closeQuietly(rebalanceCallbackMetricsManager, \"consumer rebalance callback metrics\");\n        }\n    }\n\n    // visible for testing\n    void invokeCompletedOffsetCommitCallbacks() {\n        if (asyncCommitFenced.get()) {\n            throw new FencedInstanceIdException(\"Get fenced exception for group.instance.id \"\n                + rebalanceConfig.groupInstanceId.orElse(\"unset_instance_id\")\n                + \", current member.id is \" + memberId());\n        }\n        while (true) {\n            OffsetCommitCompletion completion = completedOffsetCommits.poll();\n            if (completion == null) {\n                break;\n            }\n            completion.invoke();\n        }\n    }\n\n    public RequestFuture<Void> commitOffsetsAsync(final Map<TopicPartition, OffsetAndMetadata> offsets, final OffsetCommitCallback callback) {\n        invokeCompletedOffsetCommitCallbacks();\n\n        RequestFuture<Void> future = null;\n        if (offsets.isEmpty()) {\n            // No need to check coordinator if offsets is empty since commit of empty offsets is completed locally.","sourceCodeStart":1021,"sourceCodeEnd":1057,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java#L1021-L1057","documentation":"Thrown as FencedInstanceIdException from ConsumerCoordinator.invokeCompletedOffsetCommitCallbacks when the flag asyncCommitFenced is set. That flag is set (line 1128) when an asynchronous offset commit completed with a FENCED_INSTANCE_ID error from the broker, meaning another consumer instance using the same group.instance.id (static membership) joined the group and displaced this one. The exception is deferred until the next poll/commit invokes completed commit callbacks, so the app sees it on a normal API call.","triggerScenarios":"Two consumer processes share the same group.instance.id in the same consumer group; the second one joins and the broker fences the first. A subsequent async offset commit by the fenced instance fails with FENCED_INSTANCE_ID, setting asyncCommitFenced=true; on the next poll()/commitOffsetsAsync() invokeCompletedOffsetCommitCallbacks sees the flag and throws FencedInstanceIdException at line 1039.","commonSituations":"Static membership (group.instance.id set) deployed with duplicate ids across replicas/pods (e.g. a Deployment with replicaCount>1 reusing a fixed id, or two instances started from the same config); a process restart where the old instance did not shut down before the new one registered with the same id; misconfigured sidecar/daemon spawning duplicates.","solutions":["Give every live consumer instance a unique group.instance.id (derive it from pod name / hostname / instance id); never share it across concurrently running processes.","If this instance is legitimately the one that should be active, stop the duplicate instance and restart this consumer so it rejoins unfenced.","On catching FencedInstanceIdException, treat the instance as fenced: stop consuming and re-initialize with a fresh, unique group.instance.id (or no static membership).","Audit deployment templates (Helm/K8s) to ensure group.instance.id is templated per-pod, not hardcoded."],"exampleFix":"// before (shared static id across replicas)\nprops.put(ConsumerConfig.GROUP_INSTANCE_ID_CONFIG, \"order-consumer\");\n\n// after (unique per instance)\nprops.put(ConsumerConfig.GROUP_INSTANCE_ID_CONFIG,\n    \"order-consumer-\" + InetAddress.getLocalHost().getHostName());","handlingStrategy":"try-catch","validationCode":"String gid = (String) configs.get(ConsumerConfig.GROUP_INSTANCE_ID_CONFIG);\nif (gid != null && !gid.isEmpty()) {\n    // static membership: ensure no other process advertises the same group.instance.id.\n    // Acquire a distributed lock / lease keyed on gid before starting the consumer,\n    // or generate gid from a uniquely-assigned pod identity.\n}","typeGuard":"static boolean isFenced(Throwable t) {\n    return t instanceof org.apache.kafka.common.errors.FencedInstanceIdException;\n}","tryCatchPattern":"try {\n    consumer.poll(Duration.ofMillis(1000));\n} catch (org.apache.kafka.common.errors.FencedInstanceIdException e) {\n    // another instance with the same group.instance.id took over this membership\n    Utils.closeQuietly(consumer, \"fenced consumer\");\n    // recreate the consumer, ideally after ensuring the old instance is gone\n    consumer = new KafkaConsumer<>(configs);\n}","preventionTips":["Ensure group.instance.id is unique per running process","Never run two consumers with the same static member id concurrently","On fencing, close the consumer and recreate it rather than retrying in place","Use dynamic membership (omit group.instance.id) unless static identity is required"],"tags":["kafka","consumer","static-membership","consumer-group","fencing","config"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}