apache/pulsar · error · IllegalArgumentException

Sink Names differ

Error message

Sink Names differ

What it means

Thrown by SinkConfigUtils.validateUpdate when an update attempt changes the sink's name. Immutable identity fields (tenant, namespace, name) are compared between the existing and new SinkConfig; any difference is rejected with IllegalArgumentException because renaming would create a different function resource.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:619

    }

    @SneakyThrows
    public static SinkConfig clone(SinkConfig sinkConfig) {
        return ObjectMapperFactory.getMapper().reader().readValue(
                ObjectMapperFactory.getMapper().writer().writeValueAsBytes(sinkConfig), SinkConfig.class);
    }

    public static SinkConfig validateUpdate(SinkConfig existingConfig, SinkConfig newConfig) {
        SinkConfig mergedConfig = clone(existingConfig);

        if (!existingConfig.getTenant().equals(newConfig.getTenant())) {
            throw new IllegalArgumentException("Tenants differ");
        }
        if (!existingConfig.getNamespace().equals(newConfig.getNamespace())) {
            throw new IllegalArgumentException("Namespaces differ");
        }
        if (!existingConfig.getName().equals(newConfig.getName())) {
            throw new IllegalArgumentException("Sink Names differ");
        }
        if (!StringUtils.isEmpty(newConfig.getClassName())) {
            mergedConfig.setClassName(newConfig.getClassName());
        }
        if (!StringUtils.isEmpty(newConfig.getSourceSubscriptionName()) && !newConfig.getSourceSubscriptionName()
                .equals(existingConfig.getSourceSubscriptionName())) {
            throw new IllegalArgumentException("Subscription Name cannot be altered");
        }

        if (newConfig.getInputSpecs() == null) {
            newConfig.setInputSpecs(new HashMap<>());
        }

        if (mergedConfig.getInputSpecs() == null) {
            mergedConfig.setInputSpecs(new HashMap<>());
        }
        if (!StringUtils.isEmpty(newConfig.getLogTopic())) {
            mergedConfig.setLogTopic(newConfig.getLogTopic());

View on GitHub (pinned to 820761864e)

Solutions

  1. Restore the original sink name in the config used for the update
  2. If a rename is intended, delete the old sink and create a new one (update does not support rename)
  3. Verify with 'pulsar-admin sinks get' which name is deployed and use that in tenant/namespace/name triple

Example fix

// before
sinkConfig.setName("my-sink-v2");
admin.sinks().updateSink(tenant, namespace, sinkConfig, null);
// after
sinkConfig.setName("my-sink"); // keep existing name
admin.sinks().updateSink(tenant, namespace, sinkConfig, null);
Defensive patterns

Strategy: validation

Validate before calling

if (!existing.getName().equals(newCfg.getName())) {
    throw new IllegalArgumentException("Sink name is immutable; expected " + existing.getName());
}
admin.sinks().updateSink(existing.getTenant(), existing.getNamespace(), newCfg, null);

Try / catch

try {
    admin.sinks().updateSink(tenant, namespace, cfg, null);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Sink Names differ")) { /* reset name to existing and retry once */ }
    else throw e;
}

Prevention

When it happens

Trigger: Calling Pulsar Functions update-sink (or admin API updateSink) with a SinkConfig whose getName() differs from the currently deployed sink, e.g. editing the 'name' field in a YAML config used for update.

Common situations: Developers copy a sink config from another sink or rename the sink in a config file, then run 'pulsar-admin sinks update' instead of 'create'; CI pipelines regenerate configs with a new name.

Related errors


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