Skip to content

Debug Tracing

A request returns an unexpected status code and you need to identify which middleware in the pipeline rejected it.

Enable debug mode to populate a _trace object on error responses. The trace shows which middleware ran and which one triggered the pipeline break.

import http from "node:http";
import {
handler, compose, logger, authorization, body,
} from "@centralping/ergo";
const pipeline = compose(
{fn: logger(), setPath: "log"},
{fn: authorization({ strategies }), setPath: "auth"},
{fn: body(), setPath: "body"},
(req, res, acc) => ({
response: { body: acc.body.parsed, statusCode: 200 },
}),
);
const server = http.createServer(
handler(pipeline, { debug: true }),
);
server.listen(3000);

When a request is rejected (e.g. missing authorization), the error response body includes a _trace field:

{
"type": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401",
"title": "Unauthorized",
"status": 401,
"_trace": {
"steps": ["log", "auth"],
"breakAt": "auth"
}
}

When debug is true, the pipeline initializes a trace object on the response accumulator before running middleware:

responseAcc._trace = { steps: [], breakAt: undefined };

As each middleware executes, its label (the setPath from the {fn, setPath} config object, or the function name) is pushed onto steps. When a middleware sets responseAcc.statusCode and triggers a pipeline break, breakAt records that middleware’s label.

FieldTypeDescription
stepsstring[]Middleware labels in execution order
breakAtstring | undefinedLabel of the middleware that caused the pipeline break

_trace is not in send()’s reserved key set. On error responses (statusCode ≥ 400), it appears as an RFC 9457 extension member in the response body alongside type, title, status, and detail. On success responses (2xx), _trace is not included in the body.

When debug is false (the default), no trace object is created and the pipeline skips all label-tracking logic. There is no performance cost in production.

Pipeline debug tracing (_trace) is unrelated to the OpenTelemetry tracing middleware. OTel tracing populates domainAcc.trace with distributed trace context (trace ID, span ID) for production observability. Debug tracing populates responseAcc._trace with pipeline execution details for local debugging. Both can be active simultaneously without conflict.