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
- Serialize the body as FunctionMetaData::writeTo protobuf bytes, not JSON or form data.
- Verify the payload was not truncated: compare sent byte count with FunctionMetaData's serialized size.
- 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
- Always send FunctionMetaData.toByteArray() with an application/x-protobuf content type.
- Never send JSON to the updateOnLeader endpoint; it is protobuf-only.
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
- e.getMessage()
- No Function %s found
- Function package is not provided
- Cannot terminate non-persistent topic: ${segmentTopic}
- <validation message from IllegalArgumentException>
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/219a77e0a7267543.
Report an issue: GitHub.