{"record":{"id":"0a1fce303d442bdd","repo":"aeron-io/aeron","slug":"srcarchive-pollforerrorresponse","errorCode":null,"errorMessage":"srcArchive.pollForErrorResponse()","messagePattern":"srcArchive\\.pollForErrorResponse\\(\\)","errorType":"exception","errorClass":"ArchiveException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/ReplicationSession.java","lineNumber":998,"sourceCode":"            null == reason ? \"\" : reason);\n        state = newState;\n        activeCorrelationId = NULL_VALUE;\n        timeOfLastActionMs = epochClock.time();\n    }\n\n    private void pollSourceArchiveEvents()\n    {\n        if (null != srcArchive && State.DONE != state && NULL_VALUE == activeCorrelationId)\n        {\n            final long nowMs = epochClock.time();\n            if (nowMs > (timeOfLastScheduledSourceArchivePollMs + SOURCE_ARCHIVE_POLL_INTERVAL_MS))\n            {\n                timeOfLastScheduledSourceArchivePollMs = nowMs;\n\n                final String errorMessage = srcArchive.pollForErrorResponse();\n                if (null != errorMessage)\n                {\n                    throw new ArchiveException(errorMessage);\n                }\n            }\n        }\n    }\n\n    private void logStateChange(\n        final State oldState,\n        final State newState,\n        final long replicationId,\n        final long srcRecordingId,\n        final long dstRecordingId,\n        final long position,\n        final String reason)\n    {\n        ArchiveTracing.traceReplicationSessionStateChange(\n            oldState, newState, replicationId, srcRecordingId, dstRecordingId, position, reason);\n    }\n","sourceCodeStart":980,"sourceCodeEnd":1016,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/ReplicationSession.java#L980-L1016","documentation":"ReplicationSession periodically polls the source archive client for an error response (srcArchive.pollForErrorResponse()); if the source Aeron client/archive reports any error, its message is rethrown as an ArchiveException on the destination side, aborting replication. This surfaces source-side client failures (e.g. driver errors, failed control requests) so replication does not hang while the source is broken.","triggerScenarios":"The source Archive client's underlying Aeron client or control requests enter an error state — e.g. the media driver dies, a control request fails, or the archive client records an error — and the periodic pollForErrorResponse check in checkSourceArchiveErrors/progress path (ReplicationSession.java:998) observes the non-null error message.","commonSituations":"Source Aeron driver terminated or crashed during replication; source archive client's control channel failed; driver timeout on the source host; shared driver shutdown taking the archive client down.","solutions":["Check the source machine's driver and archive logs for the underlying error matching the propagated message.","Restart the source media driver / archive and re-issue the replication.","Ensure the source Aeron client used for replication is dedicated and not closed while replication runs.","Monitor both drivers' health (aeronstat / driver heartbeat) to detect source-side failure before replication stalls."],"exampleFix":"// before\nfinal long replicationId = dstArchive.replication(srcRecordingId, channel); // assumes source stays healthy\n// after\nif (!srcArchive.isClosed() && srcArchive.pollForErrorResponse() == null) {\n    final long replicationId = dstArchive.replication(srcRecordingId, channel);\n} else {\n    log.error(\"source archive client in error state; fix source before replicating\");\n}","handlingStrategy":"try-catch","validationCode":"// Ensure the source archive client has no pending error before relying on it:\nString err = sourceArchive.pollForErrorResponse();\nif (err != null) throw new IllegalStateException(\"source archive client in error state: \" + err);","typeGuard":null,"tryCatchPattern":"try {\n    replicationId = archive.replication(srcRecordingId, channel);\n} catch (ArchiverException e) {\n    // message is the source client's error text\n    log.error(\"replication aborted due to source client error: \" + e.getMessage());\n    restartSourceAndReplicate(srcRecordingId, channel);\n}","preventionTips":["Run the source Aeron media driver under supervision (systemd/daemontools) so a driver crash is restarted promptly.","Do not close the source Archive client or its Aeron client while replication sessions are active.","Poll pollForErrorResponse() on your own archive clients routinely to catch failures early.","Keep driver resources (memory, file stores) healthy on the source host to avoid driver timeouts."],"tags":["aeron-archive","replication","source-failure","driver"],"backgroundTag":"upstream-api-error","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}