oracle/graal · error · UnsupportedOperationException

file attributes: {attrs}

Error message

file attributes: {attrs}

What it means

FileAttributeParser.parseWithDefault only understands the 'posix:permissions' FileAttribute; anything else (e.g. 'dos:readonly', 'basic:lastModifiedTime', or a custom attribute) throws UnsupportedOperationException listing the attributes. This backs file creation in the Truffle NIO provider where only POSIX permission masks can be translated.

Source

Thrown at espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/FileAttributeParser.java:67

                    OTHERS_EXECUTE_VALUE;
    static final int ALL_READWRITE = OWNER_READ_VALUE |
                    OWNER_WRITE_VALUE |
                    GROUP_READ_VALUE |
                    GROUP_WRITE_VALUE |
                    OTHERS_READ_VALUE |
                    OTHERS_WRITE_VALUE;

    static int parseWithDefault(int defaultAttrs, FileAttribute<?>... attrs) {
        if (attrs == null || attrs.length == 0) {
            return defaultAttrs;
        }
        for (FileAttribute<?> attr : attrs) {
            if (attr.name().equals("posix:permissions")) {
                @SuppressWarnings("unchecked")
                Set<PosixFilePermission> perms = (Set<PosixFilePermission>) attr.value();
                return getMaskfromPosix(perms);
            } else {
                throw new UnsupportedOperationException("file attributes: " + Arrays.toString(attrs));
            }
        }
        throw new IllegalStateException("should not reach here");
    }

    private static int getMaskfromPosix(Set<PosixFilePermission> perms) {
        int mask = 0;
        for (PosixFilePermission perm : perms) {
            switch (perm) {
                case OWNER_READ:
                    mask |= OWNER_READ_VALUE;
                    break;
                case OWNER_WRITE:
                    mask |= OWNER_WRITE_VALUE;
                    break;
                case OWNER_EXECUTE:
                    mask |= OWNER_EXECUTE_VALUE;
                    break;

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Pass only PosixFilePermissions.asFileAttribute(...) style attributes.
  2. Set other metadata after creation via Files.setAttribute/Files.setLastModifiedTime, which are separate code paths.
  3. Branch on the provider/OS before attaching attributes.

Example fix

// before
Files.createFile(p, DosFileAttributeView...
// e.g. attribute "dos:readonly"

// after
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-r--r--");
Files.createFile(p, PosixFilePermissions.asFileAttribute(perms));
Files.setLastModifiedTime(p, FileTime.from(millis, TimeUnit.MILLISECONDS)); // set times separately
Defensive patterns

Strategy: validation

Validate before calling

static boolean isSupported(FileAttribute<?> a) {
    return "posix:permissions".equals(a.name());
}
// filter attrs before Files.createFile

Try / catch

try {
    Files.createFile(p, attrs);
} catch (UnsupportedOperationException e) {
    if (e.getMessage().startsWith("file attributes")) {
        Files.createFile(p); // create bare, set metadata afterwards
    }
}

Prevention

When it happens

Trigger: Guest code calling Files.createFile/createDirectory/createSymbolicLink with FileAttribute<?> other than posix:permissions, e.g. Windows DOS attributes or NFS/basic timestamps, on the Truffle filesystem provider.

Common situations: Cross-platform code that sets dos:* attributes on Windows-targeted logic but runs on Espresso's POSIX-style Truffle FS; libraries constructing files with metadata attributes unconditionally.

Related errors


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