{"record":{"id":"e553a1abf8abf584","repo":"conductor-oss/conductor","slug":"streaming-produced-no-events-stream-may-have-drop","errorCode":null,"errorMessage":"Streaming produced no events (stream may have dropped); will retry","messagePattern":"Streaming produced no events \\(stream may have dropped\\); will retry","errorType":"exception","errorClass":"A2AException","httpStatus":null,"severity":"warning","filePath":"ai/src/main/java/org/conductoross/conductor/ai/tasks/worker/A2AWorkers.java","lineNumber":402,"sourceCode":"            return null;\n        }\n        return StringUtils.trimToNull(agent.path(\"a2a\").path(\"agentCard\").path(\"url\").asText(null));\n    }\n\n    private void startRemote(Task task, TaskResult result, A2ACallRequest request) {\n        try {\n            A2AMessage message = buildMessage(request, task);\n            SendResult sendResult;\n            if (request.isStreaming()) {\n                sendResult =\n                        a2aService.streamMessage(\n                                request.getAgentUrl(),\n                                message,\n                                buildConfiguration(request, task, result, false),\n                                request.getHeaders(),\n                                maxDurationSeconds(request));\n                if (!sendResult.isTask() && isEmptyMessage(sendResult.getMessage())) {\n                    throw new A2AException(\n                            \"Streaming produced no events (stream may have dropped); will retry\");\n                }\n            } else {\n                boolean usePush = usePush(request);\n                sendResult =\n                        a2aService.sendMessage(\n                                request.getAgentUrl(),\n                                message,\n                                buildConfiguration(request, task, result, usePush),\n                                request.getHeaders());\n            }\n            applySendResult(result, request, sendResult);\n        } catch (NonRetryableException e) {\n            fail(result, e.getMessage(), true);\n        } catch (Exception e) {\n            fail(result, \"Failed to call agent: \" + e.getMessage(), false);\n        }\n    }","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/tasks/worker/A2AWorkers.java#L384-L420","documentation":"Thrown as A2AException (a retryable failure) during a streaming A2A call when sendResult.isTask() is false AND the returned A2AMessage is empty (null, or null/empty parts). It means the SSE/stream transport opened but delivered no usable events, so the call is treated as a transient drop and will be retried. Unlike NonRetryableException, this maps to a retryable task failure, not a terminal one.","triggerScenarios":"Calling an A2A agent with request.isStreaming()=true where the stream closes immediately, emits only keep-alive/comment events, or the server returns a 200 with an empty event body. Also when the remote agent returns a non-task message object with zero parts.","commonSituations":"Upstream agent crash mid-handshake; load balancer/proxy buffering or dropping SSE frames; network interruption that closes the stream before the first data event; agent that does not actually implement streaming and returns an empty 200; TLS/proxy timeout truncating the stream.","solutions":["Retry the workflow task — this is designed to be retried (it is an A2AException, not NonRetryableException).","If it persists, test the remote agent's streaming endpoint directly with curl to confirm it emits SSE data events.","Check proxy/LB SSE settings (disable buffering, raise idle timeout) between Conductor and the agent.","If the agent does not support streaming, set request.isStreaming()=false to use the non-streaming sendMessage path.","Verify the remote agent returns either a JSON-RPC task object or a non-empty message in the stream."],"exampleFix":"// before\nrequest.setStreaming(true);  // agent emits no events -> retry storm\n// after\nrequest.setStreaming(false);  // use unary send when agent lacks real streaming","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// A2AException is retryable by design; let the task runner retry, or catch to add backoff/jitter.\ntry {\n    sendResult = a2aService.streamMessage(...);\n} catch (A2AException e) {\n    // transient stream drop — schedule a retry with backoff\n    result.setStatus(TaskResult.Status.IN_PROGRESS);\n    result.setCallbackAfterSeconds(retryBackoffSeconds);\n}","preventionTips":["Configure SSE-friendly proxies (disable buffering, raise idle timeout) on the path to the agent.","Disable streaming (isStreaming=false) for agents that do not emit real SSE events.","Monitor retry frequency for a given agent to detect chronic stream drops."],"tags":["a2a","streaming","sse","retryable","network"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}