apache/pulsar · error · RuntimeException
RuntimeException(err)
Error message
RuntimeException(err)
What it means
The namespaces getTiDBLedgers (offloaded-ledger scan) endpoint writes a JSON response through a StreamingOutput; any exception raised inside that streaming lambda is logged and rethrown as a raw RuntimeException(err). Because streaming has already begun, the broker cannot convert it into a clean HTTP status, so the client typically sees a 500 or a truncated response body.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Namespaces.java:3622
}
String json = objectWriter().writeValueAsString(data);
out.write(json);
}
@Override
public void finished(int total, int errors, int unknown) throws Exception {
out.append("]\n");
out.append("\"total\": " + total + ",\n");
out.append("\"errors\": " + errors + ",\n");
out.append("\"unknown\": " + unknown + "\n");
}
});
out.append("}");
out.flush();
outputStream.flush();
} catch (Exception err) {
log.error().exception(err).log("error");
throw new RuntimeException(err);
}
};
return Response.ok(output).type(MediaType.APPLICATION_JSON_TYPE).build();
} catch (Throwable err) {
log.error()
.attr("namespace", namespaceName)
.exception(err)
.log("Error while scanning offloaded ledgers for namespace");
throw new RestException(Response.Status.INTERNAL_SERVER_ERROR,
"Error while scanning ledgers for " + namespaceName);
}
}
@GET
@Path("/{tenant}/{namespace}/entryFilters")
@Operation(summary = "Get maxConsumersPerSubscription config on a namespace.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Get maxConsumersPerSubscription config on a namespace.",View on GitHub (pinned to 820761864e)
Solutions
- Check the broker log for the accompanying 'error' entry to find the root cause exception wrapped in the RuntimeException.
- Verify connectivity to the metadata service and offload storage (e.g. ledger offload driver credentials/bucket) and retry the scan.
- Retry the request; if it recurs for large namespaces, narrow the scan scope or increase relevant timeouts.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!admin.namespaces().getNamespaces(tenant).contains(tenant + "/" + namespace)) {
throw new IllegalStateException("namespace does not exist");
} Try / catch
try {
return admin.namespaces().getTiDBLedgers(tenant, namespace);
} catch (PulsarAdminException e) {
if (e instanceof PulsarAdminException.HttpErrorException
&& ((PulsarAdminException.HttpErrorException) e).getStatusCode() == 500) {
// streaming failed mid-way; inspect broker logs and retry with backoff
return retryWithBackoff(() -> admin.namespaces().getTiDBLedgers(tenant, namespace));
}
throw e;
} Prevention
- Ensure metadata-service and offload-storage connectivity before running scans.
- Handle truncated response bodies on 500s — data streamed before failure is incomplete.
- Keep scans scoped and schedule them off-peak to avoid stream timeouts.
When it happens
Trigger: GET /admin/v2/namespaces/{tenant}/{namespace}/tiDBLedgers (scan of offloaded ledgers) where an exception occurs while iterating ledgers or writing JSON to the output stream — e.g. metadata-service read failure or connection drop mid-stream.
Common situations: Underlying storage/meta store connectivity problems during the scan; very large namespace scans hitting timeouts; client disconnects causing stream write IOException; permission or topic-level errors surfacing after the response streaming started.
Related errors
- Error while scanning ledgers for ${namespaceName}
- ${loadManagerClass} does not support this operation
- Unauthorized to validateBothSuperuserAndBrokerOperation for
- Number of transaction coordinators should be more than the c
- Bookie 'group' parameters is missing
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b28cf1bf9d3a40c3.
Report an issue: GitHub.