oracle/graal · error · UnsupportedOperationException

link option: {}

Error message

link option: {}

What it means

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.

Source

Thrown at espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TrufflePath.java:183

    @Override
    public URI toUri() {
        return URI.create(toURI0());
    }

    @Override
    public Path toAbsolutePath() {
        return new TrufflePath(getTruffleFileSystem(), toAbsolutePath0());
    }

    static boolean followLinks(LinkOption... options) {
        if (options != null && options.length > 0) {
            for (LinkOption option : options) {
                Objects.requireNonNull(option);
                if (option == LinkOption.NOFOLLOW_LINKS) {
                    return false;
                } else {
                    throw new UnsupportedOperationException("link option: " + option);
                }
            }
        }
        return true;
    }

    @Override
    public Path toRealPath(LinkOption... options) throws IOException {
        return new TrufflePath(getTruffleFileSystem(), toRealPath0(followLinks(options)));
    }

    @Override
    public WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers) throws IOException {
        throw new UnsupportedOperationException();
    }

    @Override
    public int compareTo(Path other) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Pass only LinkOption.NOFOLLOW_LINKS or an empty varargs array
  2. Remove custom LinkOption subclasses from your API and model extra flags separately
  3. Check for shadowed java.nio.file classes on the guest classpath

Example fix

// before
path.toRealPath(myCustomNofollow);

// after
path.toRealPath(LinkOption.NOFOLLOW_LINKS);
Defensive patterns

Strategy: type-guard

Validate before calling

for (LinkOption o : options) {
    if (o != LinkOption.NOFOLLOW_LINKS) throw new UnsupportedOperationException("link option: " + o);
}

Type guard

static boolean isSupportedLinkOption(LinkOption... options) {
    for (LinkOption o : options) {
        if (o != LinkOption.NOFOLLOW_LINKS) return false;
    }
    return true;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/2abd1a88b8e7fa07. Report an issue: GitHub.