pinpoint-apm/pinpoint · warning

Already closed

Error message

Already closed {}

What it means

ChildTrace.close0() logs 'Already closed {}' as a warning when close0() is invoked on a ChildTrace instance whose `closed` flag is already true. ChildTrace is a lightweight per-span trace object, and the library guards against double-close so the underlying TraceRoot is not finalized twice. The warning means some code path closed the trace more than once; the second close is a no-op.

Solutions

  1. Remove redundant close() calls from application/plugin code and let the agent manage the trace lifecycle
  2. Guard your own cleanup with an idempotency check (e.g. a local AtomicBoolean) before calling close()
  3. Ensure each Trace obtained from TraceContext is closed exactly once per request thread
  4. If seen after upgrading, check the agent version for known double-close bugs in async trace handling

Example fix

// before
Trace trace = traceContext.newTraceObject();
doWork();
trace.close();
trace.close(); // warns Already closed
// after
Trace trace = traceContext.newTraceObject();
doWork();
trace.close();
Defensive patterns

Strategy: try-catch

Validate before calling

// check before cleanup
if (trace != null && !isTraceClosed(trace)) {
    trace.close();
}

Type guard

boolean isOpen(Trace t) { return t != null && !isClosedFlagSet(t); }

Try / catch

try { trace.close(); } catch (RuntimeException e) { logger.debug("trace close skipped", e); }

Prevention

When it happens

Trigger: Calling close() (which delegates to close0()) twice on the same ChildTrace, e.g. manual close() followed by framework/agent-triggered cleanup, or a finally-block close after the agent already closed the trace when the call stack was force-completed.

Common situations: Plugin/interceptor code that explicitly closes traces plus an agent-side cleanup path both firing; async trace completion racing with synchronous close; reusing a Trace reference after its lifecycle ended.

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


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

Appendix: source

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

    }


    @Override
    public boolean isClosed() {
        return closed;
    }

    @Override
    public void close() {
        if (asyncTraceBlock) {
            traceBlockEnd(ASYNC_BEGIN_STACK_ID);
        }
        close0();
    }

    public void close0() {
        if (closed) {
            logger.warn("Already closed {}", this);
            return;
        }
        closed = true;

        if (!callStack.empty()) {
            if (logger.isWarnEnabled()) {
                stackDump("not empty call stack");
            }
            // skip
        } else {
            logSpan();
        }
        this.wrappedSpanEventRecorder.close();
        this.storage.close();
    }

    @Override
    public TraceId getTraceId() {

View on GitHub (pinned to 744c3d3075)