apache/pulsar · error · RestException

e.getMessage()

Error message

e.getMessage()

What it means

HTTP 400 thrown by FunctionsImplV2.registerFunction when the submitted functionDetailsJson cannot be parsed into a FunctionDetails proto JSON. Any parse/validation exception (bad JSON syntax, missing required fields like className/inputs, invalid enum values) is caught and its message returned as the 400 body.

Source

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

        for (FunctionStatus.FunctionInstanceStatus instanceStatus : functionStatus.instances) {
            toProto(functionStatusList.addFunctionStatus(),
                    instanceStatus.getStatus(),
                    String.valueOf(instanceStatus.getInstanceId()));
        }
        String jsonResponse = functionStatusList.toJson();
        return Response.status(Response.Status.OK).entity(jsonResponse).build();
    }

    @Override
    public Response registerFunction(String tenant, String namespace, String functionName, InputStream
            uploadedInputStream, FormDataContentDisposition fileDetail, String functionPkgUrl, String
                                             functionDetailsJson, AuthenticationParameters authParams) {

        FunctionDetails functionDetails = new FunctionDetails();
        try {
            functionDetails.parseFromJson(functionDetailsJson);
        } catch (Exception e) {
            throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
        }
        FunctionConfig functionConfig = FunctionConfigUtils.convertFromDetails(functionDetails);

        delegate.registerFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
                functionPkgUrl, functionConfig, authParams);
        return Response.ok().build();
    }

    @Override
    public Response updateFunction(String tenant, String namespace, String functionName,
                                   InputStream uploadedInputStream, FormDataContentDisposition fileDetail,
                                   String functionPkgUrl, String functionDetailsJson,
                                   AuthenticationParameters authParams) {

        FunctionDetails functionDetails = new FunctionDetails();
        try {
            functionDetails.parseFromJson(functionDetailsJson);
        } catch (Exception e) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Validate the JSON against FunctionDetails proto format: required top-level fields and correct enum spellings (e.g. RuntimeType JAVA).
  2. Use FunctionDetails::toJson (or FunctionConfigUtils.convertToDetails on a FunctionConfig) client-side to generate the payload instead of hand-writing JSON.
  3. Read the 400 message body — protobuf JSON parse errors usually name the offending field or token.

Example fix

// before
String details = "{\"classname\": \"com.ex.Fn\"}"; // typo'd field
// after
FunctionDetails details = FunctionConfigUtils.convertToDetails(functionConfig);
registerFunction(tenant, ns, name, stream, fileDetail, pkgUrl, details.toJson(), authParams);
Defensive patterns

Strategy: validation

Validate before calling

try {
    FunctionDetails details = FunctionDetails.parseFromJson(functionDetailsJson); // dry-run parse client-side
} catch (Exception e) {
    throw new IllegalArgumentException("invalid functionDetails JSON: " + e.getMessage());
}

Type guard

function isJsonObject(s) {
  try { return JSON.parse(s) !== null && typeof JSON.parse(s) === 'object'; } catch { return false; }
}

Try / catch

try {
    admin.registerFunctionV2(..., functionDetailsJson);
} catch (ApiException e) {
    if (e.code() == 400) {
        // log e.body(): names the JSON parse/validation failure
    }
}

Prevention

When it happens

Trigger: POSTing to the V2 functions registration endpoint with a functionDetails field that is not valid JSON, or JSON missing required FunctionDetails fields (tenant, namespace, name, className, inputs, output, runtime), or an unknown runtime/enum string.

Common situations: Hand-rolled JSON payloads with typo'd field names (e.g. 'classname' vs 'className'); passing the whole FunctionConfig JSON (source/sink shape) where FunctionDetails proto JSON is expected; double-encoding the JSON string; schema drift after upgrading Pulsar so previously-valid fields are rejected.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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