apache/pulsar · error · ConflictException

Failed to update to value

Error message

Failed to update to value:%s

What it means

ConflictException thrown by MetadataStoreTableViewImpl.put when the underlying metadata-store update fails with BadVersionException, meaning another writer changed the entry between the cached read and the CAS update attempt.

Solutions

  1. Catch ConflictException from the put future and retry with a fresh read (the tableview re-reads before next attempt).
  2. Use a distinct key per writer, or shard keys to avoid hot-key contention.
  3. Enable/verify the conflictResolver design accounts for optimistic-concurrency retries.
  4. Reduce write frequency to the same key, or serialize writes through a single owner.

Example fix

// before
return cache.readModifyUpdateOrCreate(path, mutator);
// after
return FutureUtil.retryFailedAsync(() -> cache.readModifyUpdateOrCreate(path, mutator), retryPolicy);
Defensive patterns

Strategy: retry

Try / catch

CompletableFuture<Void> put = tableView.put(key, value);
put.exceptionally(ex -> {
    if (FutureUtil.unwrapCompletionException(ex) instanceof ConflictException) {
        // BadVersion case: retry after fresh read with backoff
        return null;
    }
    throw FutureUtil.wrapToCompletionException(ex);
});

Prevention

When it happens

Trigger: Two clients call put on the same key concurrently; the second update's expected version no longer matches the store's version, so cache.readModifyUpdateOrCreate fails with MetadataStoreException.BadVersionException and is translated into this ConflictException.

Common situations: Multiple brokers/producers writing the same tableview key at once, a delete racing with a put on the same key, or retry loops that hammer one hot key.

Related errors


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

Appendix: source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/tableview/impl/MetadataStoreTableViewImpl.java:418

    }

    public T get(String key) {
        return data.get(key);
    }

    public CompletableFuture<Void> put(String key, T value) {
        String path = getPath(key);
        return cache.readModifyUpdateOrCreate(path, (old) -> {
            if (conflictResolver.test(old.orElse(null), value)) {
                return value;
            } else {
                throw new ConflictException(
                        String.format("Failed to update from old:%s to value:%s", old, value));
            }
        }).thenCompose(__ -> doHandleNotification(path)) // immediately notify local tableview
        .exceptionally(e -> {
            if (e.getCause() instanceof MetadataStoreException.BadVersionException) {
                throw FutureUtil.wrapToCompletionException(new ConflictException(
                        String.format("Failed to update to value:%s", value)));
            }

            throw FutureUtil.wrapToCompletionException(e.getCause());
        });
    }

    public CompletableFuture<Void> delete(String key) {
        String path = getPath(key);
        return cache.delete(path)
                .thenCompose(__ -> doHandleNotification(path)); // immediately notify local tableview
    }

    public int size() {
        return immutableData.size();
    }

    public boolean isEmpty() {

View on GitHub (pinned to 820761864e)