{"record":{"id":"2abd1a88b8e7fa07","repo":"oracle/graal","slug":"link-option","errorCode":null,"errorMessage":"link option: {}","messagePattern":"link option: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TrufflePath.java","lineNumber":183,"sourceCode":"\n    @Override\n    public URI toUri() {\n        return URI.create(toURI0());\n    }\n\n    @Override\n    public Path toAbsolutePath() {\n        return new TrufflePath(getTruffleFileSystem(), toAbsolutePath0());\n    }\n\n    static boolean followLinks(LinkOption... options) {\n        if (options != null && options.length > 0) {\n            for (LinkOption option : options) {\n                Objects.requireNonNull(option);\n                if (option == LinkOption.NOFOLLOW_LINKS) {\n                    return false;\n                } else {\n                    throw new UnsupportedOperationException(\"link option: \" + option);\n                }\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public Path toRealPath(LinkOption... options) throws IOException {\n        return new TrufflePath(getTruffleFileSystem(), toRealPath0(followLinks(options)));\n    }\n\n    @Override\n    public WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers) throws IOException {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public int compareTo(Path other) {","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TrufflePath.java#L165-L201","documentation":"Thrown by TrufflePath.followLinks when a LinkOption other than LinkOption.NOFOLLOW_LINKS is passed. LinkOption is a final enum-like class with exactly one constant, so in practice this fires only for a hand-rolled LinkOption subclass or a LinkOption loaded by a different class loader whose equals() fails against the constant. toRealPath(...) is the API that routes through this check.","triggerScenarios":"Calling path.toRealPath(customLinkOption) with a non-constant LinkOption instance, or running with a shadowed java.nio.file.LinkOption class so option == LinkOption.NOFOLLOW_LINKS fails identity comparison.","commonSituations":"Framework code that subclasses LinkOption to smuggle extra flags; classpath/module-path shadowing of java.nio in the Espresso guest; version-skewed guest JDK builds.","solutions":["Pass only LinkOption.NOFOLLOW_LINKS or an empty varargs array","Remove custom LinkOption subclasses from your API and model extra flags separately","Check for shadowed java.nio.file classes on the guest classpath"],"exampleFix":"// before\npath.toRealPath(myCustomNofollow);\n\n// after\npath.toRealPath(LinkOption.NOFOLLOW_LINKS);","handlingStrategy":"type-guard","validationCode":"for (LinkOption o : options) {\n    if (o != LinkOption.NOFOLLOW_LINKS) throw new UnsupportedOperationException(\"link option: \" + o);\n}","typeGuard":"static boolean isSupportedLinkOption(LinkOption... options) {\n    for (LinkOption o : options) {\n        if (o != LinkOption.NOFOLLOW_LINKS) return false;\n    }\n    return true;\n}","tryCatchPattern":null,"preventionTips":["Pass LinkOption.NOFOLLOW_LINKS or nothing; never subclass LinkOption","Avoid classpath shadowing of java.nio.file types in guest applications"],"tags":["espresso","nio","link-option","path","truffle"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}