apache/pulsar · error · RestException

Corrupt Function MetaData

Error message

Corrupt Function MetaData

What it means

HTTP 400 thrown when the uploaded request body cannot be parsed as a FunctionMetaData protobuf (parseFrom throws IOException). The worker expects the updateOnLeader endpoint body to be a serialized FunctionMetaData proto; any bytes that are not a valid encoding of that message are rejected as corrupt metadata.

Source

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

            }
        }

        if (tenant == null) {
            throw new RestException(Response.Status.BAD_REQUEST, "Tenant is not provided");
        }
        if (namespace == null) {
            throw new RestException(Response.Status.BAD_REQUEST, "Namespace is not provided");
        }
        if (functionName == null) {
            throw new RestException(Response.Status.BAD_REQUEST, "Function name is not provided");
        }
        FunctionMetaData functionMetaData;
        try {
            byte[] data = uploadedInputStream.readAllBytes();
            functionMetaData = new FunctionMetaData();
            functionMetaData.parseFrom(data);
        } catch (IOException e) {
            throw new RestException(Response.Status.BAD_REQUEST, "Corrupt Function MetaData");
        }

        // Redirect if we are not the leader
        if (!worker().getLeaderService().isLeader()) {
            WorkerInfo workerInfo = worker().getMembershipManager().getLeader();
            if (workerInfo == null || workerInfo.getWorkerId().equals(worker().getWorkerConfig().getWorkerId())) {
                throw new RestException(Response.Status.SERVICE_UNAVAILABLE,
                        "Leader not yet ready. Please retry again");
            }
            URI redirect = UriBuilder.fromUri(uri).host(workerInfo.getWorkerHostname())
                    .port(workerInfo.getPort()).build();
            throw new WebApplicationException(Response.temporaryRedirect(redirect).build());
        }

        // Its possible that we are not the leader anymore. That will be taken care of by FunctionMetaDataManager
        FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
        try {
            functionMetaDataManager.updateFunctionOnLeader(functionMetaData, delete);

View on GitHub (pinned to 820761864e)

Solutions

  1. Serialize the body as FunctionMetaData::writeTo protobuf bytes, not JSON or form data.
  2. Verify the payload was not truncated: compare sent byte count with FunctionMetaData's serialized size.
  3. Confirm the proto schema version on the client matches the server's FunctionMetaData definition (compatible wire format).

Example fix

// before
String json = new Gson().toJson(metaData);
request.body(json);
// after
byte[] data = metaData.toByteArray();
request.body(RequestBody.create(data, MediaType.parse("application/x-protobuf")));
Defensive patterns

Strategy: try-catch

Validate before calling

byte[] data = metaData.toByteArray();
if (data.length == 0) throw new IllegalStateException("empty FunctionMetaData payload");

Try / catch

try {
    // send protobuf body
} catch (ApiException e) {
    if (e.code() == 400 && e.body().contains("Corrupt Function MetaData")) {
        // re-serialize with FunctionMetaData::toByteArray and retry once
    }
}

Prevention

When it happens

Trigger: POSTing to the updateOnLeader endpoint with a body that is JSON, form data, a truncated file, or otherwise not the exact protobuf binary encoding of FunctionMetaData; sending an empty body; a client serializing a different proto type into the stream.

Common situations: Sending JSON because the public functions API accepts JSON-based configs (version mismatch between API flavors); a proxy or client library re-encoding or chunk-truncating the binary body; uploading the wrong file (e.g. the function jar) as the metadata payload; charset/encoding mangling of the binary payload.

Related errors


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