eclipse-vertx/vert.x · error · FileSystemException

Failed to read ${link}

Error message

Failed to read ${link}

What it means

Thrown when FileSystem.readSymbolicLink fails: Vert.x calls Files.readSymbolicLink and wraps any IOException into a FileSystemException built from getFileAccessErrorMessage("read", link) — i.e. 'Failed to read <link>'. It means the path could not be resolved as a symbolic link.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java:658

        }
        return null;
      }
    };
  }

  private BlockingAction<Void> unlinkInternal(String link) {
    return deleteInternal(link);
  }

  private BlockingAction<String> readSymlinkInternal(String link) {
    Objects.requireNonNull(link);
    return new BlockingAction<String>() {
      public String perform() {
        try {
          Path source = resolveFile(link).toPath();
          return Files.readSymbolicLink(source).toString();
        } catch (IOException e) {
          throw new FileSystemException(getFileAccessErrorMessage("read", link), e);
        }
      }
    };
  }

  private BlockingAction<Void> deleteInternal(String path) {
    return deleteInternal(path, false);
  }

  private BlockingAction<Void> deleteInternal(String path, boolean recursive) {
    Objects.requireNonNull(path);
    return new BlockingAction<Void>() {
      public Void perform() {
        try {
          Path source = resolveFile(path).toPath();
          delete(source, recursive);
        } catch (IOException e) {
          throw new FileSystemException(getFileAccessErrorMessage("delete", path), e);

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Verify the path is a symlink first (check props via lprops and/or symlink attribute) before reading it.
  2. Confirm the path exists; a missing path also raises IOException here.
  3. Handle the NotLinkException cause explicitly when the input may be a regular file.
  4. On non-POSIX filesystems, skip symlink resolution entirely.

Example fix

// before
String target = vertx.fileSystem().readSymbolicLinkBlocking("/app/current"); // fails if not a link
// after
if (vertx.fileSystem().lpropsBlocking("/app/current").isSymbolicLink()) {
  String target = vertx.fileSystem().readSymbolicLinkBlocking("/app/current");
}
Defensive patterns

Strategy: validation

Validate before calling

FileProps lp = vertx.fileSystem().lpropsBlocking(link);
if (!lp.isSymbolicLink()) throw new IllegalArgumentException("not a symlink: " + link);

Try / catch

try { return vertx.fileSystem().readSymbolicLinkBlocking(link); } catch (FileSystemException e) { if (e.getCause() != null && e.getCause().getClass().getSimpleName().equals("NotLinkException")) return link; throw e; }

Prevention

When it happens

Trigger: Calling vertx.fileSystem().readSymbolicLink(link) on a path that is not a symbolic link (NotLinkException, an IOException subtype), a broken symlink, or a path that does not exist.

Common situations: Reading a regular file or directory assuming it was a symlink; resolving symlinks on filesystems that don't support them; TOCTOU where the symlink was replaced between check and read.

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


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/47e0e643d633eacd. Report an issue: GitHub.