pinpoint-apm/pinpoint · error · StatusException

INVALID_ARGUMENT

INVALID_ARGUMENT

Error message

handleCommand() not support included Header:{}. Connection will be disconnected.

What it means

Pinpoint's legacy gRPC command channel (handleCommand, the v1 API) requires that the agent's connection Header NOT carry a supportCommandCodeList; the sentinel SUPPORT_COMMAND_CODE_LIST_NOT_EXIST means the field is absent. If the agent sends a non-empty support command code list in the header, the collector treats this as a protocol violation for the v1 stream, logs a warning, fails the call with gRPC Status.INVALID_ARGUMENT, and disconnects the connection.

Source

Thrown at realtime/realtime-collector/src/main/java/com/navercorp/pinpoint/realtime/collector/receiver/grpc/GrpcCommandService.java:92

        this.activeThreadDumpSinkRepo = Objects.requireNonNull(activeThreadDumpSinkRepo, "activeThreadDumpSinkRepo");
        this.activeThreadLightDumpSinkRepo = Objects.requireNonNull(activeThreadLightDumpSinkRepo, "activeThreadLightDumpSinkRepo");
        this.echoSinkRepo = Objects.requireNonNull(echoSinkRepo, "echoSinkRepo");
    }

    @Override
    @SuppressWarnings("deprecation")
    public StreamObserver<PCmdMessage> handleCommand(StreamObserver<PCmdRequest> requestObserver) {
        final Context context = Context.current();
        Long transportId = getTransportIdFromContext(context);

        final Header header = ServerContext.getAgentInfo(context);
        ClusterKey clusterKey = getClusterKeyFromContext(header);

        logger.info("{} => local. handleCommand(). transportId:{}.", clusterKey, transportId);

        List<Integer> supportCommandCodeList = header.getSupportCommandCodeList();
        if (supportCommandCodeList != Header.SUPPORT_COMMAND_CODE_LIST_NOT_EXIST) {
            logger.warn(
                    "handleCommand() not support included Header:{}. Connection will be disconnected.",
                    Header.SUPPORT_COMMAND_CODE.name()
            );

            requestObserver.onError(new StatusException(Status.INVALID_ARGUMENT));
            return DisabledStreamObserver.instance();
        }

        AtomicReference<GrpcAgentConnection> connRef = new AtomicReference<>();
        ServerCallStreamObserver<PCmdRequest> serverCallStreamObserver =
                (ServerCallStreamObserver<PCmdRequest>) requestObserver;

        serverCallStreamObserver.setOnCancelHandler(() -> {
            GrpcAgentConnection conn = connRef.get();
            if (conn != null) {
                this.agentConnectionRepository.remove(conn);
            }
        });

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Upgrade the collector to a version that supports handleCommandV2, or downgrade the agent so it does not send supportCommandCodeList on the v1 stream
  2. If implementing a custom client on handleCommand, omit the supportCommandCodeList header field entirely (leave SUPPORT_COMMAND_CODE_LIST_NOT_EXIST)
  3. Verify agent/collector version compatibility for the profiler command service and align them to the same protocol version
  4. Check which collector instance the agent is connecting to (routing/LB may send it to a legacy collector)

Example fix

// before (agent on v1 stream sends command codes)
Header header = Header.newBuilder()
        .setName(agentName)
        .addAllSupportCommandCodeList(supportCommandCodeList) // rejected by handleCommand
        .build();
// after (use v2 stream, or omit codes on v1)
// either call profilerCommandStub.handleCommandV2(header with codes)
// or for legacy handleCommand:
Header header = Header.newBuilder()
        .setName(agentName) // no supportCommandCodeList
        .build();
Defensive patterns

Strategy: validation

Validate before calling

// client-side, before opening the v1 command stream
if (!header.getSupportCommandCodeList().isEmpty()) {
    throw new IllegalStateException("supportCommandCodeList must be omitted for handleCommand (v1); use handleCommandV2");
}

Try / catch

// server/clients observing the stream failure
try (CommandStream stream = openCommandStream(header)) {
    stream.awaitReady();
} catch (StatusRuntimeException e) {
    if (e.getStatus().getCode() == Status.Code.INVALID_ARGUMENT) {
        log.warn("v1 command stream rejected: header must not contain supportCommandCodeList", e);
    }
}

Prevention

When it happens

Trigger: An agent (or agent-like client) opens the ProfilerCommandService handleCommand stream while its Handshake/Header includes a populated supportCommandCodeList field instead of omitting it. In Pinpoint this happens when a newer agent built for the v2 API (handleCommandV2) connects to a collector that only registers/serves the legacy v1 handler.

Common situations: Version mismatch between pinpoint agent and collector: agent upgraded to the command-v2 protocol but collector still on the old version (or vice versa routing to the wrong endpoint). Custom/prototype agents copying Header building code and setting SUPPORT_COMMAND_CODE_LIST even when using the v1 stream.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


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