pinpoint-apm/pinpoint · error · IllegalStateException
cannot leave with BOUNDARY trace scope. depth: ${depth}
Error message
cannot leave with BOUNDARY trace scope. depth: ${depth} What it means
BoundaryTraceScope.leave() enforces the internal invariants of a BOUNDARY-scoped trace scope: the scope must be active, no boundary blocks may be skipped (skippedBoundary==0), and the depth must be exactly 1 when leaving. Thrown as IllegalStateException when the code attempts to leave a boundary scope that is unbalanced — i.e. an enter/leave pair mismatch.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/scope/BoundaryTraceScope.java:63
}
}
public boolean canLeave() {
if (skippedBoundary == 0 && depth == 1) {
return true;
} else {
skippedBoundary--;
return false;
}
}
public void leave() {
if (!isActive()) {
throw new IllegalStateException("cannot leave with trace scope. depth: " + depth);
}
if (skippedBoundary != 0 || depth != 1) {
throw new IllegalStateException("cannot leave with BOUNDARY trace scope. depth: " + depth);
}
depth--;
}
@Override
public boolean isActive() {
return depth > 0;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("DefaultTraceScope{");
sb.append("name='").append(name).append('\'');
sb.append(", depth=").append(depth);
sb.append(", skippedBoundary=").append(skippedBoundary);
sb.append('}');
return sb.toString();
}View on GitHub (pinned to 744c3d3075)
Solutions
- Ensure every enterBoundary() call has a matching leaveBoundary() in a finally block
- Check that skipEnterBoundary/leaveSkipBoundary pairs are balanced
- Verify the interceptor is not re-entering the same boundary scope before leaving it
- Log depth and skippedBoundary at enter/leave points to find the imbalance
Example fix
// before
trace.enterBoundary(1);
doWork();
trace.leaveBoundary(1);
// after
trace.enterBoundary(1);
try {
doWork();
} finally {
trace.leaveBoundary(1);
} Defensive patterns
Strategy: validation
Validate before calling
if (!scope.isActive() || scope.getDepth() != 1) { throw new IllegalStateException("boundary scope unbalanced before leave"); } Try / catch
try { scope.leave(); } catch (IllegalStateException e) { logger.warn("unbalanced boundary scope: {}", e.getMessage()); } Prevention
- Always pair enterBoundary with leaveBoundary in try/finally
- Track scope depth manually in complex interceptor chains
- Avoid skipping boundaries unless strictly necessary
When it happens
Trigger: Calling leave() when skippedBoundary != 0 (a boundary-skip counter was incremented by skipEnterBoundary without a matching leaveSkipBoundary) or when depth != 1 (multiple nested enters or leave called at the wrong nesting level).
Common situations: Custom trace instrumentation plugins that call enterBoundary/leaveBoundary unbalancedly (e.g. missing leave on an exception path), or re-entrancy where the interceptor enters the boundary twice but leaves once.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot leave with scope. depth: ${depth}
- UNSUPPORTED_OPERATION
- startTime not recorded
- spanEventList is empty.
- first SpanEvent is null
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/e363fd83e56cf8d9.
Report an issue: GitHub.