{"record":{"id":"c1333bec9832c983","repo":"conductor-oss/conductor","slug":"a2a-agent-card-discovery-requires-agenttype-a2a","errorCode":null,"errorMessage":"A2A agent-card discovery requires agentType 'a2a'","messagePattern":"A2A agent-card discovery requires agentType 'a2a'","errorType":"http","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/a2a/A2ACallbackResource.java","lineNumber":83,"sourceCode":"    private final A2AService a2aService;\n\n    public A2ACallbackResource(TaskService taskService, A2AService a2aService) {\n        this.taskService = taskService;\n        this.a2aService = a2aService;\n    }\n\n    /**\n     * Resolve a public A2A Agent Card using the same discovery, network policy, and SSRF checks as\n     * the {@code GET_AGENT_CARD} system task.\n     *\n     * <p>The typed result deliberately contains only the discovered card. Request headers are used\n     * for discovery but are never reflected into the response, which makes the result safe to\n     * persist as workflow task metadata.\n     */\n    @PostMapping(\"/agent-card\")\n    public A2AAgentCardResult getAgentCard(@RequestBody A2AAgentCardRequest request) {\n        if (request == null || !A2AService.isA2aAgentType(request.getAgentType())) {\n            throw new IllegalArgumentException(\"A2A agent-card discovery requires agentType 'a2a'\");\n        }\n        if (StringUtils.isBlank(request.getAgentUrl())) {\n            throw new IllegalArgumentException(\"A2A agent-card discovery requires 'agentUrl'\");\n        }\n        AgentCard card = a2aService.getAgentCard(request.getAgentUrl(), request.getHeaders());\n        return new A2AAgentCardResult(card);\n    }\n\n    @PostMapping(\"/callback/{taskId}\")\n    public ResponseEntity<Void> onPushNotification(\n            @PathVariable(\"taskId\") String taskId,\n            @RequestHeader(value = \"Authorization\", required = false) String authHeader,\n            @RequestHeader(value = \"X-Conductor-A2A-Token\", required = false) String customHeader,\n            @RequestBody(required = false) JsonNode payload) {\n\n        try (A2ALogging.Scope scope = A2ALogging.of(A2ALogging.TASK_ID, taskId)) {\n            String token = resolveToken(authHeader, customHeader);\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/a2a/A2ACallbackResource.java#L65-L101","documentation":"Thrown by the A2ACallbackResource.getAgentCard() REST endpoint (POST /api/a2a/agent-card) when the request body is null or the agentType field does not select the A2A runtime. The isA2aAgentType() check accepts null, blank, or 'a2a' (case-insensitive), so this fires only when agentType is explicitly set to a non-A2A value like 'azure-foundry' or 'conductor'.","triggerScenarios":"POST to /api/a2a/agent-card with a request body where agentType is set to a non-A2A value (e.g. 'azure-foundry', 'conductor'), or when the entire request body is null/malformed.","commonSituations":"The caller set agentType to 'azure-foundry' or 'conductor' but used the generic A2A agent-card endpoint instead of the provider-specific discovery path. The request body was not sent or was malformed JSON, resulting in a null deserialized request.","solutions":["Set agentType to 'a2a' or omit it entirely (null/blank defaults to A2A) in the request body","If using azure-foundry or conductor agents, use the appropriate discovery mechanism instead of this endpoint","Ensure the request body is valid JSON with an agentType field"],"exampleFix":"// before\n{\"agentType\": \"azure-foundry\", \"agentUrl\": \"https://my-agent.example.com\"}\n// after\n{\"agentType\": \"a2a\", \"agentUrl\": \"https://my-agent.example.com\"}","handlingStrategy":"validation","validationCode":"// Validate the request before sending to the endpoint\nif (request == null || !A2AService.isA2aAgentType(request.getAgentType())) {\n    throw new IllegalArgumentException(\n        \"agentType must be null, blank, or 'a2a' for this endpoint\");\n}","typeGuard":"// Type guard for A2AAgentCardRequest\npublic boolean isValidA2AAgentCardRequest(A2AAgentCardRequest req) {\n    return req != null\n        && A2AService.isA2aAgentType(req.getAgentType())\n        && StringUtils.isNotBlank(req.getAgentUrl());\n}","tryCatchPattern":"// This is a REST endpoint — handle via @ExceptionHandler or global advice\n// The IllegalArgumentException will be mapped to HTTP 400 by Spring if not caught","preventionTips":["Always set agentType to 'a2a' or omit it when calling the A2A agent-card endpoint","Use 'azure-foundry' or 'conductor' agentType only with their dedicated task types, not this endpoint","Validate the request body before sending if calling programmatically"],"tags":["a2a","rest-api","input-validation"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}