apache/pulsar · error · MetadataStoreException

Failed to set data for ${path}

Error message

Failed to set data for ${path}

What it means

BaseResources.set performs a read-modify-update through the cache and blocks until completion; failures (store errors, optimistic-concurrency retries exhausted, timeout, interruption) are converted into MetadataStoreException('Failed to set data for <path>'). It means a policy/resource update could not be persisted at that path.

Source

Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/resources/BaseResources.java:159

    protected CompletableFuture<Optional<T>> getAsync(String path) {
        return cache.get(path);
    }

    protected CompletableFuture<Optional<T>> refreshAndGetAsync(String path) {
        return store.sync(path).thenCompose(___ -> {
            cache.invalidate(path);
            return cache.get(path);
        });
    }

    protected void set(String path, Function<T, T> modifyFunction) throws MetadataStoreException {
        try {
            setAsync(path, modifyFunction).get(operationTimeoutSec, TimeUnit.SECONDS);
        } catch (ExecutionException e) {
            throw (e.getCause() instanceof MetadataStoreException) ? (MetadataStoreException) e.getCause()
                    : new MetadataStoreException(e.getCause());
        } catch (Exception e) {
            throw new MetadataStoreException("Failed to set data for " + path, e);
        }
    }

    protected CompletableFuture<Void> setAsync(String path, Function<T, T> modifyFunction) {
        return cache.readModifyUpdate(path, modifyFunction).thenApply(__ -> null);
    }

    protected void setWithCreate(String path, Function<Optional<T>, T> createFunction) throws MetadataStoreException {
        try {
            setWithCreateAsync(path, createFunction).get(operationTimeoutSec, TimeUnit.SECONDS);
        } catch (ExecutionException e) {
            throw (e.getCause() instanceof MetadataStoreException) ? (MetadataStoreException) e.getCause()
                    : new MetadataStoreException(e.getCause());
        } catch (Exception e) {
            throw new MetadataStoreException("Failed to set/create " + path, e);
        }
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Retry the update if caused by concurrent modification (the cache retries, but heavy contention can still fail)
  2. Check metadata store write access and quorum health
  3. Increase operationTimeoutSec for large policy documents
  4. Serialize admin updates for the same resource to reduce version conflicts

Example fix

// before
nsResources.set(path, policies -> { policies.auth_policies.put(...); return policies; });
// after
try {
    nsResources.set(path, policies -> { policies.auth_policies.put(...); return policies; });
} catch (MetadataStoreException e) {
    if (e.getCause() instanceof MetadataStoreException.BadVersionException) {
        // retry once after re-reading current policies
    } else { throw e; }
}
Defensive patterns

Strategy: retry

Validate before calling

if (!resources.exists(path)) throw new IllegalStateException("Cannot set: path missing " + path);

Try / catch

try { resources.set(path, modifier); }
catch (MetadataStoreException e) {
    if (e.getCause() instanceof MetadataStoreException.BadVersionException) { /* re-read and retry */ }
    else throw e;
}

Prevention

When it happens

Trigger: Calling set(path, modifyFunction) when the readModifyUpdate fails due to store write errors, version/BadVersion conflicts after retries, operation timeout, or interruption.

Common situations: Concurrent admin updates racing on the same path; metadata store read-only or quorum loss; ZooKeeper BadVersionException due to simultaneous writers; timeout too small during heavy update traffic.

Related errors


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