{"record":{"id":"47e0e643d633eacd","repo":"eclipse-vertx/vert.x","slug":"failed-to-read-link","errorCode":null,"errorMessage":"Failed to read ${link}","messagePattern":"Failed to read (.+?)","errorType":"exception","errorClass":"FileSystemException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java","lineNumber":658,"sourceCode":"        }\n        return null;\n      }\n    };\n  }\n\n  private BlockingAction<Void> unlinkInternal(String link) {\n    return deleteInternal(link);\n  }\n\n  private BlockingAction<String> readSymlinkInternal(String link) {\n    Objects.requireNonNull(link);\n    return new BlockingAction<String>() {\n      public String perform() {\n        try {\n          Path source = resolveFile(link).toPath();\n          return Files.readSymbolicLink(source).toString();\n        } catch (IOException e) {\n          throw new FileSystemException(getFileAccessErrorMessage(\"read\", link), e);\n        }\n      }\n    };\n  }\n\n  private BlockingAction<Void> deleteInternal(String path) {\n    return deleteInternal(path, false);\n  }\n\n  private BlockingAction<Void> deleteInternal(String path, boolean recursive) {\n    Objects.requireNonNull(path);\n    return new BlockingAction<Void>() {\n      public Void perform() {\n        try {\n          Path source = resolveFile(path).toPath();\n          delete(source, recursive);\n        } catch (IOException e) {\n          throw new FileSystemException(getFileAccessErrorMessage(\"delete\", path), e);","sourceCodeStart":640,"sourceCodeEnd":676,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java#L640-L676","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the path is a symlink first (check props via lprops and/or symlink attribute) before reading it.","Confirm the path exists; a missing path also raises IOException here.","Handle the NotLinkException cause explicitly when the input may be a regular file.","On non-POSIX filesystems, skip symlink resolution entirely."],"exampleFix":"// before\nString target = vertx.fileSystem().readSymbolicLinkBlocking(\"/app/current\"); // fails if not a link\n// after\nif (vertx.fileSystem().lpropsBlocking(\"/app/current\").isSymbolicLink()) {\n  String target = vertx.fileSystem().readSymbolicLinkBlocking(\"/app/current\");\n}","handlingStrategy":"validation","validationCode":"FileProps lp = vertx.fileSystem().lpropsBlocking(link);\nif (!lp.isSymbolicLink()) throw new IllegalArgumentException(\"not a symlink: \" + link);","typeGuard":null,"tryCatchPattern":"try { return vertx.fileSystem().readSymbolicLinkBlocking(link); } catch (FileSystemException e) { if (e.getCause() != null && e.getCause().getClass().getSimpleName().equals(\"NotLinkException\")) return link; throw e; }","preventionTips":["Check lprops().isSymbolicLink() before reading","Handle regular files as a non-error fallback","Re-check existence if symlinks may change concurrently","Skip resolution on filesystems without symlink support"],"tags":["filesystem","symlink","io","read"],"backgroundTag":"file-read-failed","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}