pinpoint-apm/pinpoint · error · IllegalStateException
traceReference is null
Error message
traceReference is null
What it means
DisableAsyncContext.bind() throws IllegalStateException('traceReference is null') when binding an async trace into a Reference that already holds a non-null value (message is misleading). It enforces the invariant that the async trace slot is empty before binding.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableAsyncContext.java:65
private Trace newAsyncContextTrace(Reference<Trace> reference) {
final Trace asyncTrace = local.asyncTraceContext().continueDisableAsyncContextTraceObject(traceRoot);
bind(reference, asyncTrace);
if (logger.isDebugEnabled()) {
logger.debug("asyncTraceContext.continueDisableAsyncContextTraceObject() AsyncTrace:{}", asyncTrace);
}
if (AsyncScopeUtils.nested(asyncTrace, ASYNC_TRACE_SCOPE)) {
return null;
}
return asyncTrace;
}
private void bind(Reference<Trace> reference, Trace asyncTrace) {
if (reference.get() != null) {
throw new IllegalStateException("traceReference is null");
}
reference.set(asyncTrace);
}
@Override
public Trace currentAsyncTraceObject() {
final Reference<Trace> reference = local.binder().get();
return reference.get();
}
@Override
public void close() {
local.binder().remove();
}
@Override
public boolean finish() {View on GitHub (pinned to 744c3d3075)
Solutions
- Bind each async trace to a fresh Reference
- Close/complete the previous async trace before rebinding
- Check for duplicate newAsyncContextTrace calls
- Upgrade to a fixed pinpoint version
Example fix
// before
bind(reference, asyncTrace); // throws if reference already set
// after
if (reference.get() == null) {
reference.set(asyncTrace);
} else {
asyncTrace.close();
} Defensive patterns
Strategy: try-catch
Validate before calling
if (reference.get() != null) {
// already bound; do not bind again
} Type guard
boolean canBind(Reference<Trace> ref) {
return ref.get() == null;
} Try / catch
try {
disableAsyncContext.bind(reference, asyncTrace);
} catch (IllegalStateException e) {
logger.warn("reference already bound in DisableAsyncContext", e);
} Prevention
- Check reference.get() before binding
- Ensure async traces are closed before reuse
- Avoid caching AsyncContext across requests
When it happens
Trigger: newAsyncContextTrace flow on DisableAsyncContext reaching bind(reference, asyncTrace) while reference.get() != null — the slot was already bound to another trace.
Common situations: Double-binding of async traces when sampling is disabled; lifecycle races reusing an already-bound reference; plugin code calling currentAsyncTraceObject repeatedly without closing traces.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- traceReference is null
- UNSUPPORTED_OPERATION
- startTime not recorded
- cannot leave with BOUNDARY trace scope. depth: ${depth}
- Cannot leave with scope. depth: ${depth}
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/faa44986aba7ac1c.
Report an issue: GitHub.