pinpoint-apm/pinpoint · warning
Cannot stop agent. Current status =
Error message
Cannot stop agent. Current status = [{}] What it means
WARN log from DefaultAgent.close() when the agent is not in the RUNNING state, so it cannot transition to STOPPED and close() returns without releasing resources. The parameter {} is the current AgentStatus (e.g. INITIALIZING, STOPPED). applicationContext.close() is skipped, which can leave background threads alive if callers assume shutdown happened.
Solutions
- Call close() only when getStatus() == AgentStatus.RUNNING; check status first.
- Make shutdown idempotent on your side with a boolean/closed flag so close() runs once.
- If the agent never started, do not call close(); dispose of the instance differently or fix the startup failure first.
- Ensure only one shutdown hook owns the agent lifecycle.
Example fix
// before
runtime.addShutdownHook(new Thread(() -> agent.close()));
agent.close(); // warn: Cannot stop agent. Current status = [STOPPED]
// after
private final AtomicBoolean closed = new AtomicBoolean(false);
void shutdown() {
if (closed.compareAndSet(false, true) && agent.getStatus() == AgentStatus.RUNNING) {
agent.close();
}
} Defensive patterns
Strategy: type-guard
Validate before calling
boolean canStop = (agent.getStatus() == AgentStatus.RUNNING); if (canStop) agent.close();
Type guard
boolean isClosable(DefaultAgent a) { return a.getStatus() == AgentStatus.RUNNING; } Try / catch
try {
if (agent.getStatus() == AgentStatus.RUNNING) agent.close();
} catch (Exception e) {
log.warn("agent shutdown failed", e); // don't rethrow from shutdown hooks
} Prevention
- Register exactly one shutdown hook that closes the agent.
- Make your teardown idempotent (compareAndSet flag) for double-close safety.
- Fix startup failures so the agent actually reaches RUNNING before cleanup runs.
When it happens
Trigger: Calling close() before start() (status INITIALIZING), calling close() twice (second call sees STOPPED), or closing during a failed startup that never reached RUNNING.
Common situations: Shutdown hooks racing each other and both calling close(); cleanup code in tests tearing down an agent that failed to start; double-close in application stop sequences.
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/2ba28ec3f774c5e2.
Report an issue: GitHub.
Appendix: source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java:267
public void run() {
logger.info("stop() started. threadName:" + Thread.currentThread().getName());
DefaultAgent.this.close();
}
});
shutdownHookRegister.register(shutdownThread);
}
}
@Override
public void close() {
synchronized (agentStatusLock) {
if (this.agentStatus == AgentStatus.RUNNING) {
changeStatus(AgentStatus.STOPPED);
} else {
logger.warn("Cannot stop agent. Current status = [{}]", this.agentStatus);
return;
}
}
logger.info("Stopping pinpoint Agent.");
this.applicationContext.close();
// for testcase
if (agentOption.isStaticResourceCleanup()) {
this.loggingSystem.close();
}
}
}
View on GitHub (pinned to 744c3d3075)