{"record":{"id":"0e423d9bae6cb474","repo":"pinpoint-apm/pinpoint","slug":"command-complete-before-establishment","errorCode":null,"errorMessage":"Command complete before establishment","messagePattern":"Command complete before establishment","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"realtime/realtime-collector/src/main/java/com/navercorp/pinpoint/realtime/collector/receiver/grpc/GrpcCommandService.java","lineNumber":263,"sourceCode":"    }\n\n    private void handleOnError(Throwable t, GrpcAgentConnection conn) {\n        if (conn == null) {\n            logger.warn(\"Command error before establishment\");\n            return;\n        }\n\n        final Status status = Status.fromThrowable(t);\n        Metadata metadata = Status.trailersFromThrowable(t);\n\n        logger.info(\"Failed to command stream, {} => local, {} {}\",\n                conn.getClusterKey(), status, metadata);\n\n    }\n\n    private void handleOnCompleted(GrpcAgentConnection conn) {\n        if (conn == null) {\n            logger.warn(\"Command complete before establishment\");\n            return;\n        }\n\n        logger.info(\"{} => local. onCompleted\", conn.getClusterKey());\n    }\n\n    @Override\n    public void commandEcho(PCmdEchoResponse response, StreamObserver<Empty> responseObserver) {\n        long sinkId = response.getCommonResponse().getResponseId();\n        final EchoPublisher publisher = this.echoSinkRepo.get(sinkId);\n        emitMono(response, responseObserver, publisher);\n        this.echoSinkRepo.invalidate(sinkId);\n    }\n\n    @Override\n    public void commandActiveThreadDump(PCmdActiveThreadDumpRes response, StreamObserver<Empty> responseObserver) {\n        long sinkId = response.getCommonResponse().getResponseId();\n        final ActiveThreadDumpPublisher publisher = this.activeThreadDumpSinkRepo.get(sinkId);","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/realtime/realtime-collector/src/main/java/com/navercorp/pinpoint/realtime/collector/receiver/grpc/GrpcCommandService.java#L245-L281","documentation":"The collector's command stream onCompleted callback fires when the client half-closes the stream. If the connection (GrpcAgentConnection) was never established/registered before completion, the handler logs 'Command complete before establishment'. Unlike the other errors in this class this is only a server-side warning log; no gRPC error is sent and no exception is thrown to the caller.","triggerScenarios":"The agent closes/completes its command stream (or the call ends) before the request observer registered the GrpcAgentConnection in the connection repository, e.g. the stream is completed immediately after handleCommand/handleCommandV2 returns or the registration raced with shutdown.","commonSituations":"Agent connecting and instantly disconnecting (crash loop, deploy restart); a health-check or misconfigured client opening and closing the stream without sending messages; network flaps during collector restart where close events arrive before registration completes.","solutions":["Check the agent logs for why the command stream was closed immediately after connecting (crash, OOM, config error)","Ensure the agent stays connected long enough for handshake/registration; fix any rapid reconnect loop","Ignore this warning if it coincides with normal agent shutdown or collector redeploy; it is informational for stray completes","If a custom client opens the stream, keep it open and complete it only after the session is finished"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// this is a server-side warning, not a thrown error; guard the lifecycle instead\nserverCallStreamObserver.setOnCancelHandler(() -> {\n    GrpcAgentConnection conn = connRef.get();\n    if (conn != null) { // handles the 'not established' case gracefully\n        agentConnectionRepository.remove(conn);\n    }\n});","preventionTips":["Investigate agents that open and immediately close the command stream (crash loops, bad config)","Treat this warning as benign during deploys/restarts; alert only when it fires at high rate","Keep command streams open for the agent session lifetime; complete them only on shutdown","Use exponential backoff on agent reconnects to avoid registration/completion races"],"tags":["grpc","pinpoint","stream-lifecycle","race-condition"],"backgroundTag":"invalid-state-transition","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}