apache/pulsar · error · RestException

e.getMessage()

Error message

e.getMessage()

What it means

During updateFunction, FunctionConfigUtils.validateUpdate merges and validates the submitted FunctionConfig against the existing one. Any validation exception is converted to HTTP 400 with the raw e.getMessage() text. Common causes include illegal field changes (e.g. changing inputs/className/topics in disallowed ways), invalid values, or version-drift between the submitted config and the stored one.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java:317

        if (!InstanceUtils.calculateSubjectType(existingComponent.getFunctionDetails()).equals(componentType)) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .attr("componentType", ComponentTypeUtils.toString(componentType)).log("/ / is not a");
            throw new RestException(Response.Status.NOT_FOUND, String.format("%s %s doesn't exist",
                    ComponentTypeUtils.toString(componentType), functionName));
        }

        FunctionConfig existingFunctionConfig = FunctionConfigUtils
                .convertFromDetails(existingComponent.getFunctionDetails());
        // The rest end points take precedence over whatever is there in function config
        functionConfig.setTenant(tenant);
        functionConfig.setNamespace(namespace);
        functionConfig.setName(functionName);
        FunctionConfig mergedConfig;
        try {
            mergedConfig = FunctionConfigUtils.validateUpdate(existingFunctionConfig, functionConfig);
        } catch (Exception e) {
            throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
        }

        if (existingFunctionConfig.equals(mergedConfig) && isBlank(functionPkgUrl) && uploadedInputStream == null
                && (updateOptions == null || !updateOptions.isUpdateAuthData())) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .log("/ / Update contains no changes");
            throw new RestException(Response.Status.BAD_REQUEST, "Update contains no change");
        }

        FunctionDetails functionDetails;
        File componentPackageFile = null;
        try {

            // validate parameters
            try {
                componentPackageFile = getPackageFile(
                        componentType,

View on GitHub (pinned to 820761864e)

Solutions

  1. Read the 400 message text — it is the validator's explanation of which field is invalid.
  2. Only mutate allowed fields: GET current config, change settings, PUT the full merged config.
  3. For immutable changes (className, inputs), delete and re-create the function.
  4. Align client and cluster Pulsar versions so config field compatibility matches.
  5. Validate the config offline with FunctionConfigUtilsUpdated/the same validation before submitting.

Example fix

// before
FunctionConfig cfg = admin.functions().getFunctionConfig(t, ns, fn);
cfg.setClassName("com.newpkg.NewClass"); // immutable -> validateUpdate throws
admin.functions().updateFunction(t, ns, fn, cfg, null);
// after
admin.functions().deleteFunction(t, ns, fn);
admin.functions().createFunction(newCfgWithNewClassName(), null);
Defensive patterns

Strategy: validation

Validate before calling

FunctionConfig current = admin.functions().getFunctionConfig(t, ns, fn);
FunctionConfig merged = mergeAndSanitize(current, submittedChanges); // only copy allowed mutable fields
try {
    FunctionConfigUtils.validateUpdate(current, merged); // same validation the worker runs
} catch (Exception e) {
    throw new IllegalArgumentException("Config will be rejected: " + e.getMessage(), e);
}

Try / catch

try {
    admin.functions().updateFunction(t, ns, fn, cfg, null);
} catch (PulsarAdminException e) {
    if (e.getStatusCode() == 400) {
        log.error("Update validation failed: {}", e.getMessage()); // raw validator reason
        throw new ConfigValidationException(e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: PUT update where the merged config violates FunctionConfig rules — changing the class name or input topics on an existing function, incompatible runtime changes, invalid parallelism/resources, or a config produced by a newer client containing fields the worker's validator rejects.

Common situations: Editing function configs via scripts that mutate the GET result incompatibly; Pulsar version mismatch where newer client config fields fail older worker validation; attempting to change immutable fields instead of delete + recreate.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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