aeron-io/aeron · error · RuntimeException
failed to read link file=" + linkFile
Error message
failed to read link file=" + linkFile
What it means
resolveMarkFileDir reads the archive link file (archive-marker.lnk style file inside the archive dir) that points to the real mark-file directory, and wraps any IOException from Files.readAllBytes in a RuntimeException 'failed to read link file=...'. This means the link file exists but could not be read (permissions, IO error, or a race where it disappeared).
Solutions
- Check OS-level permissions on the link file and archive directory (read access for the tool's user).
- Confirm the link file still exists and the archive directory is on a healthy, mounted filesystem.
- If the link file is stale/incorrect, restore it (or let a healthy archive recreate it) and retry.
Example fix
// before
// link file unreadable -> RuntimeException('failed to read link file=...')
// after
// fix permissions, then retry:
// chmod u+r /data/archive/archive-marker.lnk (run as the archive user) Defensive patterns
Strategy: try-catch
Validate before calling
File linkFile = new File(archiveDir, ArchiveTool.ARCHIVE_MARK_FILE_NAME + ".lnk");
if (linkFile.exists() && (!linkFile.canRead() || !linkFile.isFile())) {
throw new IllegalStateException("link file unreadable: " + linkFile);
} Try / catch
try (ArchiveMarkFile markFile = openMarkFile(archiveDir, out::println)) {
...
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("failed to read link file=")) {
// check permissions/mount, then retry with backoff
} else throw e;
} Prevention
- Run archive tooling as the same user that owns the archive directory files.
- Avoid deleting or touching files inside the archive dir while tools are running.
- Monitor mounts (NFS/EBS) hosting archive dirs for IO errors.
- Restore a consistent archive directory from backup if the link file is corrupt.
When it happens
Trigger: Opening the mark file (openMarkFile/openMarkFileReadWrite) when the archive directory contains a link file whose readAllBytes throws IOException: file deleted between exists() and read, unreadable permissions, disk IO error, or a bad/unreadable filesystem mount.
Common situations: Archive dir on an NFS/unstable mount; file permissions changed after container restart; concurrent tool removed the link file; read-only or failing disk.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- failed to read link file=
- Aeron client instance must set…
- Aeron client must use a RethrowingErrorHandler
- segment file length not a power of 2
- segment file length not in valid range
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/e3ee96f2e8e2a11b.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/ArchiveTool.java:1165
(version) -> {},
null);
}
private static File resolveMarkFileDir(final File archiveDir)
{
final File linkFile = new File(archiveDir, ArchiveMarkFile.LINK_FILENAME);
final File markFileDir;
if (linkFile.exists())
{
try
{
final byte[] bytes = Files.readAllBytes(linkFile.toPath());
final String markFileDirPath = new String(bytes, US_ASCII).trim();
markFileDir = new File(markFileDirPath);
}
catch (final IOException ex)
{
throw new RuntimeException("failed to read link file=" + linkFile, ex);
}
}
else
{
markFileDir = archiveDir;
}
return markFileDir;
}
private static void dump(
final PrintStream out,
final File archiveDir,
final Catalog catalog,
final long fragmentCountLimit,
final ActionConfirmation<Long> continueActionOnFragmentLimit,
final RecordingDescriptorHeaderDecoder header,
final RecordingDescriptorDecoder descriptor,View on GitHub (pinned to 6d60124e15)