apache/pulsar · error · RestException

Concurrent modification

Error message

Concurrent modification

What it means

grantPermissionsAsync detected a concurrent modification of the topic's authorization policies while writing to the metadata store (e.g., a NotFound or IllegalState race); historically mapped from grantPermissionAsync failures to keep client compatibility.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java:258

                            .log("Successfully granted access for role on topic"))
                    .exceptionally(ex -> {
                        Throwable realCause = FutureUtil.unwrapCompletionException(ex);
                        //The IllegalArgumentException and the IllegalStateException were historically thrown by the
                        // grantPermissionAsync method, so we catch them here to ensure backwards compatibility.
                        if (realCause instanceof MetadataStoreException.NotFoundException
                                || realCause instanceof IllegalArgumentException) {
                            log.warn()
                                    .attr("topic", topicUri)
                                    .exception(realCause)
                                    .log("Failed to set permissions for topic: Namespace does not exist");
                            throw new RestException(Status.NOT_FOUND, "Topic's namespace does not exist");
                        } else if (realCause instanceof MetadataStoreException.BadVersionException
                                || realCause instanceof IllegalStateException) {
                            log.warn()
                                    .attr("topic", topicUri)
                                    .exceptionMessage(realCause)
                                    .log("Failed to set permissions for topic");
                            throw new RestException(Status.CONFLICT, "Concurrent modification");
                        } else {
                            log.error()
                                    .attr("topic", topicUri)
                                    .exceptionMessage(realCause)
                                    .log("Failed to get permissions for topic");
                            throw new RestException(realCause);
                        }
                    });
        } else {
            String msg = "Authorization is not enabled";
            return FutureUtil.failedFuture(new RestException(Status.NOT_IMPLEMENTED, msg));
        }
    }

    protected void internalGrantPermissionsOnTopic(final AsyncResponse asyncResponse, String role,
                                                   Set<AuthAction> actions) {
        // This operation should be reading from zookeeper and it should be allowed without having admin privileges
        CompletableFuture<Void> validateAccessForTenantCf = validateAdminAccessForTenantAsync(namespaceName.getTenant())

View on GitHub (pinned to 820761864e)

Solutions

  1. Retry the grant — the conflict is typically transient
  2. Serialize concurrent permission changes on the same topic
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java:258 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/c707b3414de5f93a. Report an issue: GitHub.