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

  1. Check the broker log for the accompanying 'error' entry to find the root cause exception wrapped in the RuntimeException.
  2. Verify connectivity to the metadata service and offload storage (e.g. ledger offload driver credentials/bucket) and retry the scan.
  3. 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

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


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