{"record":{"id":"8ed9c468ac65cf4f","repo":"conductor-oss/conductor","slug":"a2a-stream-interrupted-8ed9c4","errorCode":null,"errorMessage":"A2A stream interrupted","messagePattern":"A2A stream interrupted","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"ai/src/main/java/org/conductoross/conductor/ai/a2a/server/A2AWorkflowAgent.java","lineNumber":335,"sourceCode":"        event.put(\"final\", isFinal);\n        return event;\n    }\n\n    private Map<String, Object> artifactUpdate(A2ATask task, Artifact artifact) {\n        Map<String, Object> event = new HashMap<>();\n        event.put(\"kind\", \"artifact-update\");\n        event.put(\"taskId\", task.getId());\n        event.put(\"contextId\", task.getContextId());\n        event.put(\"artifact\", artifact);\n        return event;\n    }\n\n    private void sleep(long millis) throws IOException {\n        try {\n            Thread.sleep(millis);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw new IOException(\"A2A stream interrupted\", e);\n        }\n    }\n\n    // ---- mapping -----------------------------------------------------------------------------\n\n    private A2ATask toA2ATask(Workflow workflow) {\n        A2ATask task = new A2ATask();\n        task.setKind(\"task\");\n        task.setId(workflow.getWorkflowId());\n        task.setContextId(workflow.getCorrelationId());\n\n        String state = mapState(workflow);\n        TaskStatus status = new TaskStatus();\n        status.setState(state);\n        String note = statusNote(workflow, state);\n        if (note != null) {\n            status.setMessage(agentTextMessage(note, workflow));\n        }","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/a2a/server/A2AWorkflowAgent.java#L317-L353","documentation":"Thrown by A2AWorkflowAgent.sleep() when the thread sleeping between SSE event emissions is interrupted. The InterruptedException is caught, the interrupt flag is restored (Thread.currentThread().interrupt()), and it is re-thrown as an IOException with message 'A2A stream interrupted'. This occurs in the A2A server (agent side), not the client side.","triggerScenarios":"During A2AWorkflowAgent streaming, the sleep() method between event emissions is interrupted by another thread calling Thread.interrupt() on the streaming thread. This can happen when the workflow is cancelled, the HTTP connection is closed by the client, or the server is shutting down.","commonSituations":"The A2A client (remote agent caller) disconnects mid-stream, causing the servlet container to interrupt the streaming thread. The underlying Conductor workflow is terminated or cancelled. Server shutdown or thread pool eviction interrupts the streaming thread. A timeout on the HTTP response triggers interruption.","solutions":["This is typically an expected interruption when a client disconnects or a workflow is cancelled — check if the workflow was intentionally terminated","Verify there are no premature connection drops caused by proxy/load-balancer idle timeouts","If using a reverse proxy, ensure idle timeout is longer than expected stream duration","Ensure the client maintains the connection for the full streaming duration"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// This is server-side — ensure the client maintains the connection\n// for the full streaming duration. No client-side validation prevents it.","typeGuard":null,"tryCatchPattern":"// In the A2AWorkflowAgent streaming handler\ntry {\n    // streaming loop with sleep()\n} catch (IOException e) {\n    if (\"A2A stream interrupted\".equals(e.getMessage())) {\n        // Thread was interrupted — likely client disconnected or workflow cancelled\n        log.info(\"A2A stream interrupted, closing gracefully\");\n        // Clean up resources and return — no need to re-throw for expected interruptions\n    } else {\n        throw e;\n    }\n}","preventionTips":["Ensure A2A clients maintain connections for the full streaming duration","Configure proxy/load-balancer idle timeouts to be longer than expected stream durations","Handle InterruptedException gracefully in streaming code by restoring the interrupt flag and cleaning up","Monitor for unexpected stream interruptions that may indicate infrastructure issues"],"tags":["a2a","streaming","interruption","server-side"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}