apache/pulsar · error · IllegalArgumentException

Namespaces differ

Error message

Namespaces differ

What it means

validateUpdate enforces that a function's namespace cannot change on update. This error is thrown when the new config's namespace differs from the existing config's namespace for the function being updated.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:991

            doPythonChecks(functionConfig);
        } else {
            throw new IllegalArgumentException("Function language runtime is either not set or cannot be determined");
        }
    }

    public static ExtractedFunctionDetails validateJavaFunction(FunctionConfig functionConfig,
                                                                ValidatableFunctionPackage validatableFunctionPackage) {
        doCommonChecks(functionConfig);
        return doJavaChecks(functionConfig, validatableFunctionPackage);
    }

    public static FunctionConfig validateUpdate(FunctionConfig existingConfig, FunctionConfig newConfig) {
        FunctionConfig mergedConfig = existingConfig.toBuilder().build();
        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("Function Names differ");
        }
        if (!StringUtils.isEmpty(newConfig.getClassName())) {
            mergedConfig.setClassName(newConfig.getClassName());
        }

        if (!StringUtils.isEmpty(newConfig.getJar())) {
            mergedConfig.setJar(newConfig.getJar());
        }

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

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

View on GitHub (pinned to 820761864e)

Solutions

  1. Set the namespace in the update payload equal to the existing function's namespace.
  2. To relocate the function, delete it and register it in the desired namespace.
  3. Double-check tenant/namespace name casing and separators in the config.

Example fix

// before
updateConfig.setNamespace("public/prod"); // existing is public/default
// after
updateConfig.setNamespace(existingConfig.getNamespace()); // "public/default"
Defensive patterns

Strategy: validation

Validate before calling

if (!existingConfig.getNamespace().equals(newConfig.getNamespace())) {
    throw new IllegalArgumentException("Update payload must reuse namespace " + existingConfig.getNamespace());
}

Type guard

boolean sameNamespace(FunctionConfig a, FunctionConfig b) {
    return a.getNamespace().equals(b.getNamespace());
}

Try / catch

try {
    merged = FunctionConfigUtils.validateUpdate(existing, updated);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("Namespaces differ")) {
        updated.setNamespace(existing.getNamespace());
        merged = FunctionConfigUtils.validateUpdate(existing, updated);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling the update function admin API with a FunctionConfig whose getNamespace() differs from the existing function's namespace (e.g. updating public/default function with namespace public/prod).

Common situations: Environment promotion workflows that swap namespace in a shared config; typo in namespace; moving a function between namespaces without first deleting it.

Related errors


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