apache/incubator-seata · warning · NotSupportYetException

not support atomic operation putConfigIfAbsent

Error message

not support atomic operation putConfigIfAbsent

What it means

ZookeeperConfiguration.putConfigIfAbsent unconditionally throws NotSupportYetException. Although Curator offers transactional APIs, this implementation has not wired them up for the create-if-absent contract, so Seata fails fast instead of emulating atomicity over zkClient.setData().

Source

Thrown at config/seata-config-zk/src/main/java/org/apache/seata/config/zk/ZookeeperConfiguration.java:246

    protected void createPersistent(String path, String data) {
        byte[] dataBytes = data.getBytes(CHARSET);
        try {
            zkClient.create().forPath(path, dataBytes);
        } catch (KeeperException.NodeExistsException e) {
            try {
                zkClient.setData().forPath(path, dataBytes);
            } catch (Exception e1) {
                throw new IllegalStateException(e.getMessage(), e1);
            }
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    @Override
    public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) {
        throw new NotSupportYetException("not support atomic operation putConfigIfAbsent");
    }

    @Override
    public boolean removeConfig(String dataId, long timeoutMills) {
        if (!seataConfig.isEmpty()) {
            seataConfig.remove(dataId);
            createPersistent(getConfigPath(), getSeataConfigStr());
            return true;
        }

        FutureTask<Boolean> future = new FutureTask<>(() -> {
            String path = buildPath(dataId);
            return deletePath(path);
        });
        CONFIG_EXECUTOR.execute(future);
        try {
            return future.get(timeoutMills, TimeUnit.MILLISECONDS);
        } catch (Exception e) {

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Use putConfig after verifying absence with getConfig if the race window is acceptable
  2. Catch NotSupportYetException and degrade to putConfig semantics
  3. Provision config nodes out-of-band with a Curator transaction (create().withMode(CreateMode.PERSISTENT).forPath...) in your own tooling
  4. Switch to a backend implementing putConfigIfAbsent if the contract is a hard requirement

Example fix

// before
configuration.putConfigIfAbsent(dataId, content, timeoutMills);

// after
if (configuration.getConfig(dataId, timeoutMills) == null) {
    configuration.putConfig(dataId, content, timeoutMills);
}
Defensive patterns

Strategy: fallback

Validate before calling

if (configuration instanceof ZookeeperConfiguration) { /* avoid putConfigIfAbsent; check-then-put */ }

Type guard

boolean supportsPutIfAbsent(Configuration c) { return !(c instanceof ZookeeperConfiguration); }

Try / catch

try { configuration.putConfigIfAbsent(id, content, timeout); } catch (NotSupportYetException e) { if (configuration.getConfig(id, timeout) == null) configuration.putConfig(id, content, timeout); }

Prevention

When it happens

Trigger: Calling Configuration.putConfigIfAbsent(dataId, content, timeoutMills) while seata is configured with config.type = zk — typically from config import/export tooling or programmatic config bootstrapping.

Common situations: Running a config migration/import tool against a Zookeeper-backed Seata installation, or writing custom provisioning code that assumes every Configuration implementation supports atomic put-if-absent.

Related errors


AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14). Data as JSON: /api/errors/a18993fbfd77025c. Report an issue: GitHub.