{"record":{"id":"823160e2ab258492","repo":"aeron-io/aeron","slug":"failed-to-list-remote-recording-descriptor","errorCode":null,"errorMessage":"failed to list remote recording descriptor","messagePattern":"failed to list remote recording descriptor","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/ReplicationSession.java","lineNumber":458,"sourceCode":"\n        return workCount;\n    }\n\n    private int replicateDescriptor()\n    {\n        int workCount = 0;\n\n        if (NULL_VALUE == activeCorrelationId)\n        {\n            final long correlationId = aeron.nextCorrelationId();\n            if (srcArchive.archiveProxy().listRecording(srcRecordingId, correlationId, srcArchive.controlSessionId()))\n            {\n                workCount += trackAction(correlationId);\n                srcArchive.recordingDescriptorPoller().reset(correlationId, 1, this);\n            }\n            else if (epochClock.time() >= (timeOfLastActionMs + actionTimeoutMs))\n            {\n                throw new TimeoutException(\"failed to list remote recording descriptor\");\n            }\n        }\n        else\n        {\n            final RecordingDescriptorPoller poller = srcArchive.recordingDescriptorPoller();\n            final int fragments = poller.poll();\n\n            if (poller.isDispatchComplete() && poller.remainingRecordCount() > 0)\n            {\n                final String errorMsg = \"unknown src recording id \" + srcRecordingId;\n                state(State.DONE, errorMsg);\n                error(errorMsg, ArchiveException.UNKNOWN_RECORDING);\n            }\n\n            if (0 == fragments && epochClock.time() >= (timeOfLastActionMs + actionTimeoutMs))\n            {\n                throw new TimeoutException(\"failed to fetch remote recording descriptor\");\n            }","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/ReplicationSession.java#L440-L476","documentation":"ReplicationSession throws this TimeoutException during the initial phase of replication: it polls the source archive for the recording descriptor (RecordingDescriptorPoller) and if no descriptor arrives within actionTimeoutMs of timeOfLastActionMs, it gives up. Replication cannot proceed without the remote descriptor, which supplies the recording identity and positions needed to set up the replays that transfer the data.","triggerScenarios":"replicateDescriptor (driven from doWork) polls srcArchive.recordingDescriptorPoller() but receives no matching descriptor fragment before epochClock.time() >= timeOfLastActionMs + actionTimeoutMs. Causes: source archive unreachable or slow, wrong recordingId queried on the source, control-request/response channel congestion, source archive overloaded, or the archive's default timeout too small for a slow remote.","commonSituations":"Network partitions or high latency between source and destination archives; requesting replication of a recordingId that does not exist (or was already purged) on the source archive; firewalls blocking the control channel so the response never arrives; a destination archive configured with an actionTimeoutMs shorter than the source's response time under load.","solutions":["Verify the source recordingId exists on the source archive (list recordings via AeronArchive.listRecording) before replicating","Check connectivity between the two archives: control channels, name resolution and firewall rules for the archive control endpoints","Increase the destination archive's action timeout (actionTimeoutMs / replication timeout config) if the source is slow but reachable","Retry the replication once the source archive is healthy; add application-level retry around AeronArchive.replicate with backoff"],"exampleFix":"// before: no existence check, no retry\narchive.replicate(recordingId, dstRecordingId, srcControlChannel, srcReplicationChannel);\n\n// after: verify the descriptor exists, then replicate\nif (archive.listRecording(recordingId) == null) {\n    throw new IllegalStateException(\"recording not found on source: \" + recordingId);\n}\narchive.replicate(recordingId, dstRecordingId, srcControlChannel, srcReplicationChannel);","handlingStrategy":"retry","validationCode":"try (AeronArchive probe = AeronArchive.connect(new AeronArchive.Context().controlChannel(srcControlChannel))) {\n    if (probe.listRecording(sourceRecordingId) == null) {\n        throw new IllegalArgumentException(\"recording not found on source archive: \" + sourceRecordingId);\n    }\n}","typeGuard":"static boolean sourceArchiveReachable(String controlChannel, long timeoutMs) {\n    try (AeronArchive a = AeronArchive.connect(new AeronArchive.Context().controlChannel(controlChannel))) {\n        return a.archiveProxy().timeOfLastStatusMessage() > 0 || a.archiveClientProxy() != null;\n    } catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n    replicationId = archive.replicate(recordingId, dstRecordingId, srcControlChannel, srcReplicationChannel);\n} catch (TimeoutException e) {\n    if (e.getMessage().contains(\"failed to list remote recording descriptor\")) {\n        backoffAndRetryReplication(recordingId, dstRecordingId, maxAttempts); // check source connectivity/recordingId between attempts\n    } else { throw e; }\n}","preventionTips":["Confirm the recordingId exists on the source archive before initiating replication","Test source archive control-channel connectivity (and firewall rules) before starting replication","Set actionTimeoutMs large enough to cover cross-datacenter latency and source load spikes","Add idempotent application-level retries with backoff around replicate() calls"],"tags":["archive","replication","timeout","remote-archive"],"backgroundTag":"request-timeout","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"}