{"record":{"id":"89dc865f26043389","repo":"oracle/graal","slug":"copy-option","errorCode":null,"errorMessage":"copy option: {}","messagePattern":"copy option: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TruffleFileSystemProvider.java","lineNumber":211,"sourceCode":"                    StandardOpenOption.DELETE_ON_CLOSE,\n                    StandardOpenOption.SPARSE,\n                    StandardOpenOption.SYNC,\n                    StandardOpenOption.DSYNC,\n                    LinkOption.NOFOLLOW_LINKS);\n\n    // Keep in sync with Target_*_TruffleFileSystemProvider#SUPPORTED_COPY_OPTIONS.\n    private static final List<CopyOption> SUPPORTED_COPY_OPTIONS = List.of(\n                    StandardCopyOption.REPLACE_EXISTING,\n                    StandardCopyOption.COPY_ATTRIBUTES,\n                    StandardCopyOption.ATOMIC_MOVE,\n                    LinkOption.NOFOLLOW_LINKS);\n\n    private static int copyOptionsToMask(CopyOption... options) {\n        int mask = 0;\n        for (CopyOption option : options) {\n            int index = SUPPORTED_COPY_OPTIONS.indexOf(option);\n            if (index < 0) {\n                throw new UnsupportedOperationException(\"copy option: \" + option);\n            }\n            assert index < 32;\n            mask |= 1 << index;\n        }\n        return mask;\n    }\n\n    private static int openOptionsToMask(Set<? extends OpenOption> options) {\n        int mask = 0;\n        for (OpenOption option : options) {\n            int index = SUPPORTED_OPEN_OPTIONS.indexOf(option);\n            if (index < 0) {\n                throw new UnsupportedOperationException(\"open option: \" + option);\n            }\n            mask |= 1 << index;\n        }\n        return mask;\n    }","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TruffleFileSystemProvider.java#L193-L229","documentation":"Thrown by TruffleFileSystemProvider.copyOptionsToMask when a CopyOption passed to copy() or move() is not in SUPPORTED_COPY_OPTIONS. Only REPLACE_EXISTING, COPY_ATTRIBUTES, ATOMIC_MOVE, and LinkOption.NOFOLLOW_LINKS are forwarded to the native layer; any other implementation of CopyOption (the interface has only those standard constants) cannot be represented in the option bitmask.","triggerScenarios":"Calling Files.copy/Files.move on TrufflePaths with a custom CopyOption implementation, or a third-party library passing its own option objects.","commonSituations":"Cross-filesystem utilities written against other providers (e.g. a custom extended-attributes copy option) reused against the Truffle file system; option objects from a different class loader failing equals() against the standard constants.","solutions":["Restrict options to StandardCopyOption.REPLACE_EXISTING / COPY_ATTRIBUTES / ATOMIC_MOVE and LinkOption.NOFOLLOW_LINKS","If ATOMIC_MOVE is rejected downstream on cross-store moves, retry without it","Filter unknown options out (with a warning) before calling copy/move in generic utility code"],"exampleFix":"// before\nFiles.copy(src, dst, new MyFastCopyOption()); // custom CopyOption\n\n// after\nFiles.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);","handlingStrategy":"validation","validationCode":"private static final Set<CopyOption> TRUFFLE_COPY_OPTIONS = Set.of(\n    StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES,\n    StandardCopyOption.ATOMIC_MOVE, LinkOption.NOFOLLOW_LINKS);\nfor (CopyOption o : options) {\n    if (!TRUFFLE_COPY_OPTIONS.contains(o)) throw new UnsupportedOperationException(\"copy option: \" + o);\n}","typeGuard":null,"tryCatchPattern":"catch (UnsupportedOperationException e) { log and retry Files.copy(src, dst) with no options; }","preventionTips":["In generic file utilities, filter options against provider.getSupportedFileAttributeViews()/known constants before copying","Remember ATOMIC_MOVE support may still fail at runtime on cross-store moves"],"tags":["espresso","nio","copy","file-system","truffle"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}