pinpoint-apm/pinpoint · error · UnsupportedOperationException

UNSUPPORTED_OPERATION

Error message

UNSUPPORTED_OPERATION

What it means

DisableTrace is Pinpoint's no-op Trace used when sampling is disabled; nearly all of its methods intentionally throw UnsupportedOperationException to signal that tracing operations are meaningless without an active sampled trace. getTraceId() is one of those stubs: a disabled trace has no trace context, so asking for its TraceId is unsupported. If you see this, code is interacting with a trace object that was never meant to carry real span data.

Source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableTrace.java:116

    }

    @Override
    public void traceBlockEnd(int stackId) {
        pop();
    }

    private int push() {
        return this.depth++;
    }

    private void pop() {
        this.depth--;
    }


    @Override
    public TraceId getTraceId() {
        throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
    }

    @Override
    public boolean canSampled() {
        // always return false
        return false;
    }

    @Override
    public boolean isRoot() {
        return false;
    }

    @Override
    public boolean isAsync() {
        return false;
    }

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Check trace.canSampled() before calling getTraceId(); treat a disabled trace as having no trace ID.
  2. Wrap trace access in a null-object/facade that returns a placeholder TraceId (or skips logging) when sampling is off.
  3. Fix sampling configuration (profiler.sampling.type / sampling.rate) if traces were expected to be sampled.
  4. In plugin code, branch on whether the Trace is DisableTrace / isSampled and use the async or no-op variant appropriate for the interceptor.
  5. Upgrade Pinpoint if a bundled plugin is calling getTraceId on disabled traces — newer versions guard against this.

Example fix

// before
String id = trace.getTraceId().getTransactionIdAsString();
// after
if (trace.canSampled()) {
    String id = trace.getTraceId().getTransactionIdAsString();
} else {
    String id = null; // trace is disabled, no TraceId exists
}
Defensive patterns

Strategy: validation

Validate before calling

if (trace != null && trace.canSampled()) {
    TraceId traceId = trace.getTraceId(); // safe
} else {
    // trace is disabled; skip trace-id usage
}

Type guard

boolean isUsableTrace(com.navercorp.pinpoint.bootstrap.context.Trace t) {
    return t != null && t.canSampled();
}

Try / catch

try {
    TraceId id = trace.getTraceId();
} catch (UnsupportedOperationException e) {
    logger.debug("Trace is disabled, no TraceId available", e);
}

Prevention

When it happens

Trigger: Calling getTraceId() on a Trace obtained when canSampled() is false — i.e. the sampler decided not to sample the request (sampling rate 0, rate-limit sampling, or DisableTraceFactory produced the trace), and application or plugin code still calls trace.getTraceId().

Common situations: Applications that pass a Trace into custom interceptor/plugin code assuming it is always a real trace; sampling-rate misconfiguration making all traces disabled while instrumentation still queries trace IDs; tests injecting DisableTrace and exercising code paths that read the TraceId.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/0462de1accf76278. Report an issue: GitHub.