enso-org / enso

Enso Analytics is a self-service data prep and analysis platform designed for data teams.
https://ensoanalytics.com
Apache License 2.0
7.38k stars 323 forks source link

`File.new` crashes if unexpected characters are encountered in the path #9723

Closed radeusgd closed 4 months ago

radeusgd commented 7 months ago

See the followin REPL session:

> File.new "C:\dev"
>>> (File C:\dev)
> File.new "C:\dev:a"
Evaluation failed with: Illegal char <:> at index 6: C:\dev:a
java.lang.Exception: Illegal char <:> at index 6: C:\dev:a
        at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:204)
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:175)
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
        at sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
        at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:231)
        at com.oracle.truffle.polyglot.FileSystems$NIOFileSystem.parsePath(FileSystems.java:865)
        at com.oracle.truffle.api.TruffleLanguage$Env.getPublicTruffleFile(TruffleLanguage.java:2887)
        at org.enso.interpreter.runtime.EnsoContext.getPublicTruffleFile(EnsoContext.java:865)
        at org.enso.interpreter.runtime.data.EnsoFile.fromString(EnsoFile.java:317)
        at org.enso.interpreter.node.expression.builtin.io.GetFileFileNode.doString(GetFileFileNode.java:32)
        at org.enso.interpreter.node.expression.builtin.io.GetFileFileNodeGen.execute(GetFileFileNodeGen.java:48)
        at org.enso.interpreter.node.expression.builtin.io.GetFileFileMethodGen.handleExecute(GetFileFileMethodGen.java:137)
        at org.enso.interpreter.node.expression.builtin.io.GetFileFileMethodGen$1Inlineable.call(GetFileFileMethodGen.java:86)
        at org.enso.interpreter.node.callable.ExecuteCallNode.callInlineable(ExecuteCallNode.java:64)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeCall(ExecuteCallNodeGen.java:77)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.doCall(CurryNode.java:159)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.execute(CurryNode.java:107)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode.invokeCached(InvokeFunctionNode.java:116)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.execute(InvokeFunctionNodeGen.java:81)
        at org.enso.interpreter.node.callable.InvokeMethodNode.doFunctionalDispatchCachedSymbol(InvokeMethodNode.java:161)
        at org.enso.interpreter.node.callable.InvokeMethodNodeGen.execute(InvokeMethodNodeGen.java:194)
        at org.enso.interpreter.node.callable.InvokeCallableNode.invokeDynamicSymbol(InvokeCallableNode.java:268)
        at org.enso.interpreter.node.callable.InvokeCallableNodeGen.execute(InvokeCallableNodeGen.java:149)
        at org.enso.interpreter.node.callable.ApplicationNode.executeGeneric(ApplicationNode.java:97)
        at org.enso.interpreter.node.ClosureRootNode.execute(ClosureRootNode.java:85)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callDirect(OptimizedCallTarget.java:535)
        at com.oracle.truffle.runtime.OptimizedDirectCallNode.call(OptimizedDirectCallNode.java:94)
        at org.enso.interpreter.node.callable.thunk.ThunkExecutorNode.doCached(ThunkExecutorNode.java:66)
        at org.enso.interpreter.node.callable.thunk.ThunkExecutorNodeGen.executeThunk(ThunkExecutorNodeGen.java:123)
        at org.enso.interpreter.node.expression.builtin.bool.IfThenElseNode.execute(IfThenElseNode.java:29)
        at org.enso.interpreter.node.expression.builtin.bool.IfThenElseMethodGen.handleExecute(IfThenElseMethodGen.java:125)
        at org.enso.interpreter.node.expression.builtin.bool.IfThenElseMethodGen$1Inlineable.call(IfThenElseMethodGen.java:87)
        at org.enso.interpreter.node.callable.ExecuteCallNode.callInlineable(ExecuteCallNode.java:64)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeCall(ExecuteCallNodeGen.java:77)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.doCall(CurryNode.java:159)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.execute(CurryNode.java:107)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode.invokeCached(InvokeFunctionNode.java:116)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.execute(InvokeFunctionNodeGen.java:81)
        at org.enso.interpreter.node.callable.InvokeMethodNode.doFunctionalDispatchCachedSymbol(InvokeMethodNode.java:161)
        at org.enso.interpreter.node.callable.InvokeMethodNodeGen.execute(InvokeMethodNodeGen.java:194)
        at org.enso.interpreter.node.callable.InvokeCallableNode.invokeDynamicSymbol(InvokeCallableNode.java:268)
        at org.enso.interpreter.node.callable.InvokeCallableNodeGen.execute(InvokeCallableNodeGen.java:149)
        at org.enso.interpreter.node.callable.ApplicationNode.executeGeneric(ApplicationNode.java:97)
        at org.enso.interpreter.node.callable.function.BlockNode.executeGeneric(BlockNode.java:54)
        at org.enso.interpreter.node.ClosureRootNode.execute(ClosureRootNode.java:85)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callDirect(OptimizedCallTarget.java:535)
        at com.oracle.truffle.runtime.OptimizedDirectCallNode.call(OptimizedDirectCallNode.java:94)
        at org.enso.interpreter.node.controlflow.caseexpr.BranchNode.accept(BranchNode.java:45)
        at org.enso.interpreter.node.controlflow.caseexpr.CatchTypeBranchNode.execute(CatchTypeBranchNode.java:37)
        at org.enso.interpreter.node.controlflow.caseexpr.CaseNode.doMatch(CaseNode.java:117)
        at org.enso.interpreter.node.controlflow.caseexpr.CaseNodeGen.executeGeneric(CaseNodeGen.java:92)
        at org.enso.interpreter.node.callable.function.BlockNode.executeGeneric(BlockNode.java:54)
        at org.enso.interpreter.node.callable.function.BlockNode.executeGeneric(BlockNode.java:54)
        at org.enso.interpreter.node.ClosureRootNode.execute(ClosureRootNode.java:85)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callDirect(OptimizedCallTarget.java:535)
        at com.oracle.truffle.runtime.OptimizedDirectCallNode.call(OptimizedDirectCallNode.java:94)
        at org.enso.interpreter.node.callable.ExecuteCallNode.callDirect(ExecuteCallNode.java:94)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeAndSpecialize(ExecuteCallNodeGen.java:171)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeCall(ExecuteCallNodeGen.java:101)
        at org.enso.interpreter.node.callable.dispatch.SimpleCallOptimiserNode.executeDispatch(SimpleCallOptimiserNode.java:56)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.doCall(CurryNode.java:161)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.execute(CurryNode.java:107)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode.invokeCached(InvokeFunctionNode.java:116)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.executeAndSpecialize(InvokeFunctionNodeGen.java:137)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.execute(InvokeFunctionNodeGen.java:99)
        at org.enso.interpreter.node.callable.InvokeMethodNode.doFunctionalDispatchCachedSymbol(InvokeMethodNode.java:161)
        at org.enso.interpreter.node.callable.InvokeMethodNodeGen.executeAndSpecialize(InvokeMethodNodeGen.java:586)
        at org.enso.interpreter.node.callable.InvokeMethodNodeGen.execute(InvokeMethodNodeGen.java:507)
        at org.enso.interpreter.node.callable.InvokeCallableNode.invokeDynamicSymbol(InvokeCallableNode.java:268)
        at org.enso.interpreter.node.callable.InvokeCallableNodeGen.executeAndSpecialize(InvokeCallableNodeGen.java:218)
        at org.enso.interpreter.node.callable.InvokeCallableNodeGen.execute(InvokeCallableNodeGen.java:170)
        at org.enso.interpreter.node.callable.ApplicationNode.executeGeneric(ApplicationNode.java:97)
        at org.enso.interpreter.node.expression.debug.CaptureResultScopeNode.executeGeneric(CaptureResultScopeNode.java:69)
        at org.enso.interpreter.node.expression.debug.CaptureResultScopeNode.executeGeneric(CaptureResultScopeNode.java:10)
        at org.enso.interpreter.node.ClosureRootNode.execute(ClosureRootNode.java:85)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callDirect(OptimizedCallTarget.java:535)
        at com.oracle.truffle.runtime.OptimizedDirectCallNode.call(OptimizedDirectCallNode.java:94)
        at org.enso.interpreter.node.callable.thunk.ThunkExecutorNode.doCached(ThunkExecutorNode.java:69)
        at org.enso.interpreter.node.callable.thunk.ThunkExecutorNodeGen.executeAndSpecialize(ThunkExecutorNodeGen.java:208)
        at org.enso.interpreter.node.callable.thunk.ThunkExecutorNodeGen.executeThunk(ThunkExecutorNodeGen.java:168)
        at org.enso.interpreter.node.expression.debug.EvalNode.doCached(EvalNode.java:121)
        at org.enso.interpreter.node.expression.debug.EvalNodeGen.executeAndSpecialize(EvalNodeGen.java:171)
        at org.enso.interpreter.node.expression.debug.EvalNodeGen.execute(EvalNodeGen.java:99)
        at org.enso.interpreter.instrument.ReplDebuggerInstrument$ReplExecutionEventNodeImpl.evaluate(ReplDebuggerInstrument.java:136)
        at org.enso.interpreter.instrument.DebuggerMessageHandler.onMessage(DebuggerMessageHandler.scala:81)
        at org.enso.interpreter.instrument.DebuggerMessageHandler.sendBinary(DebuggerMessageHandler.scala:33)
        at com.oracle.truffle.api.instrumentation.TruffleInstrument$Env$MessageTransportProxy$MessageEndpointProxy.sendBinary(TruffleInstrument.java:1222)
        at org.enso.polyglot.debugger.DebuggerSessionManagerEndpoint$ReplExecutorImplementation.evaluate(DebuggerSessionManagerEndpoint.scala:76)
        at org.enso.runner.Repl.startSession(Repl.scala:179)
        at org.enso.polyglot.debugger.DebuggerSessionManagerEndpoint.startNewSession(DebuggerSessionManagerEndpoint.scala:40)
        at org.enso.polyglot.debugger.DebuggerSessionManagerEndpoint.handleResponse(DebuggerSessionManagerEndpoint.scala:57)
        at org.enso.polyglot.debugger.DebuggerSessionManagerEndpoint.sendBinary(DebuggerSessionManagerEndpoint.scala:19)
        at com.oracle.truffle.api.instrumentation.TruffleInstrument$Env$MessageTransportProxy$MessageEndpointProxy.sendBinary(TruffleInstrument.java:1222)
        at org.enso.interpreter.instrument.DebuggerMessageHandler.sendToClient(DebuggerMessageHandler.scala:45)
        at org.enso.interpreter.instrument.DebuggerMessageHandler.startSession(DebuggerMessageHandler.scala:61)
        at org.enso.interpreter.instrument.ReplDebuggerInstrument$ReplExecutionEventNodeImpl.startSession(ReplDebuggerInstrument.java:210)
        at org.enso.interpreter.instrument.ReplDebuggerInstrument$ReplExecutionEventNodeImpl.onEnter(ReplDebuggerInstrument.java:183)
        at com.oracle.truffle.api.instrumentation.ProbeNode$EventProviderChainNode.innerOnEnter(ProbeNode.java:1499)
        at com.oracle.truffle.api.instrumentation.ProbeNode$EventChainNode.onEnter(ProbeNode.java:980)
        at com.oracle.truffle.api.instrumentation.ProbeNode.onEnter(ProbeNode.java:226)
        at org.enso.interpreter.node.expression.builtin.debug.DebugBreakpointNodeWrapper.execute(DebugBreakpointNodeWrapper.java:44)
        at org.enso.interpreter.node.expression.builtin.debug.DebugBreakpointMethodGen.execute(DebugBreakpointMethodGen.java:91)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callDirect(OptimizedCallTarget.java:535)
        at com.oracle.truffle.runtime.OptimizedDirectCallNode.call(OptimizedDirectCallNode.java:94)
        at org.enso.interpreter.node.callable.ExecuteCallNode.callDirect(ExecuteCallNode.java:94)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeAndSpecialize(ExecuteCallNodeGen.java:171)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeCall(ExecuteCallNodeGen.java:101)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.doCall(CurryNode.java:159)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.execute(CurryNode.java:107)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode.invokeCached(InvokeFunctionNode.java:116)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.executeAndSpecialize(InvokeFunctionNodeGen.java:137)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.execute(InvokeFunctionNodeGen.java:99)
        at org.enso.interpreter.node.callable.InvokeMethodNode.doFunctionalDispatchCachedSymbol(InvokeMethodNode.java:161)
        at org.enso.interpreter.node.callable.InvokeMethodNodeGen.executeAndSpecialize(InvokeMethodNodeGen.java:586)
        at org.enso.interpreter.node.callable.InvokeMethodNodeGen.execute(InvokeMethodNodeGen.java:507)
        at org.enso.interpreter.node.callable.InvokeCallableNode.invokeDynamicSymbol(InvokeCallableNode.java:268)
        at org.enso.interpreter.node.callable.InvokeCallableNodeGen.executeAndSpecialize(InvokeCallableNodeGen.java:218)
        at org.enso.interpreter.node.callable.InvokeCallableNodeGen.execute(InvokeCallableNodeGen.java:170)
        at org.enso.interpreter.node.callable.ApplicationNode.executeGeneric(ApplicationNode.java:97)
        at org.enso.interpreter.node.callable.function.BlockNode.executeGeneric(BlockNode.java:54)
        at org.enso.interpreter.node.ClosureRootNode.execute(ClosureRootNode.java:85)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callDirect(OptimizedCallTarget.java:535)
        at com.oracle.truffle.runtime.OptimizedDirectCallNode.call(OptimizedDirectCallNode.java:94)
        at org.enso.interpreter.node.callable.ExecuteCallNode.callDirect(ExecuteCallNode.java:94)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeAndSpecialize(ExecuteCallNodeGen.java:171)
        at org.enso.interpreter.node.callable.ExecuteCallNodeGen.executeCall(ExecuteCallNodeGen.java:101)
        at org.enso.interpreter.node.callable.dispatch.SimpleCallOptimiserNode.executeDispatch(SimpleCallOptimiserNode.java:56)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.doCall(CurryNode.java:161)
        at org.enso.interpreter.node.callable.dispatch.CurryNode.execute(CurryNode.java:107)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode.invokeCached(InvokeFunctionNode.java:116)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.executeAndSpecialize(InvokeFunctionNodeGen.java:137)
        at org.enso.interpreter.node.callable.dispatch.InvokeFunctionNodeGen.execute(InvokeFunctionNodeGen.java:99)
        at org.enso.interpreter.node.callable.InteropApplicationNode.callCached(InteropApplicationNode.java:81)
        at org.enso.interpreter.node.callable.InteropApplicationNodeGen.executeAndSpecialize(InteropApplicationNodeGen.java:153)
        at org.enso.interpreter.node.callable.InteropApplicationNodeGen.execute(InteropApplicationNodeGen.java:102)
        at org.enso.interpreter.runtime.callable.function.Function$Execute.doCall(Function.java:202)
        at org.enso.interpreter.runtime.callable.function.FunctionGen$InteropLibraryExports$Cached.executeAndSpecialize(FunctionGen.java:122)
        at org.enso.interpreter.runtime.callable.function.FunctionGen$InteropLibraryExports$Cached.execute(FunctionGen.java:108)
        at com.oracle.truffle.api.interop.InteropLibrary$Asserts.execute(InteropLibrary.java:3132)
        at com.oracle.truffle.polyglot.PolyglotValueDispatch$InteropValue$SharedExecuteNode.doDefault(PolyglotValueDispatch.java:4607)
        at com.oracle.truffle.polyglot.PolyglotValueDispatchFactory$InteropValueFactory$SharedExecuteNodeGen$Inlined.executeAndSpecialize(PolyglotValueDispatchFactory.java:9528)
        at com.oracle.truffle.polyglot.PolyglotValueDispatchFactory$InteropValueFactory$SharedExecuteNodeGen$Inlined.executeShared(PolyglotValueDispatchFactory.java:9480)
        at com.oracle.truffle.polyglot.PolyglotValueDispatch$InteropValue$ExecuteNode.doDefault(PolyglotValueDispatch.java:4689)
        at com.oracle.truffle.polyglot.PolyglotValueDispatchFactory$InteropValueFactory$ExecuteNodeGen.executeImpl(PolyglotValueDispatchFactory.java:9886)
        at com.oracle.truffle.polyglot.HostToGuestRootNode.execute(HostToGuestRootNode.java:124)
        at com.oracle.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:745)
        at com.oracle.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:669)
        at com.oracle.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:602)
        at com.oracle.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:586)
        at com.oracle.truffle.runtime.OptimizedRuntimeSupport.callProfiled(OptimizedRuntimeSupport.java:266)
        at com.oracle.truffle.polyglot.PolyglotValueDispatch$InteropValue.execute(PolyglotValueDispatch.java:2637)
        at org.graalvm.polyglot.Value.execute(Value.java:930)
        at org.enso.polyglot.Function.execute(Function.scala:16)
        at org.enso.runner.Main$.runMain(Main.scala:855)
        at org.enso.runner.Main$.runRepl(Main.scala:931)
        at org.enso.runner.Main$.runMain(Main.scala:1227)
        at org.enso.runner.Main$.$anonfun$main$8(Main.scala:1100)
        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
        at org.enso.runner.Main$.withProfiling(Main.scala:1296)
        at org.enso.runner.Main$.$anonfun$main$7(Main.scala:1100)
        at org.enso.runner.Main$.$anonfun$main$7$adapted(Main.scala:1100)
        at scala.util.Either.fold(Either.scala:189)
        at org.enso.runner.Main$.main(Main.scala:1100)
        at org.enso.runner.Main.main(Main.scala)
        at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.lang.reflect.Method.invoke(Method.java:580)
        at org.enso.EngineRunnerBootLoader.main(EngineRunnerBootLoader.java:46)

Expected behaviour

A harmless dataflow error should be raised, telling that the path is invalid (e.g. Illegal_Argument).

Actual behaviour

The operation crashes. I think this is not even a panic but interpreter crash.

It may be that this only occurs on Windows as the stack trace hints Windows-specific methods.

radeusgd commented 7 months ago

Indeed, on Linux it seems that such weird paths are accepted:

> File.new "C:/a"
>>> (File C:/a)
> File.new "a:b:c"
>>> (File a:b:c)
> File.new "C:\dev:a"
>>> (File C:\dev:a)
> File.new "C:\dev:a" . exists
>>> false
JaroslavTulach commented 4 months ago

Possible fix:

diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java
index 5d2de7614..a674321f2 100644
--- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java
+++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java
@@ -451,7 +451,12 @@ public final class EnsoFile implements EnsoObject {
       return noSuchFileException;
     }

-    var parent = fromString(EnsoContext.get(null), path).truffleFile.getParent();
+    var parent =
+        switch (fromString(EnsoContext.get(null), path)) {
+          case EnsoFile f -> f.truffleFile.getParent();
+          case null -> null;
+          default -> null;
+        };
     // Unknown parent, so the heuristic cannot be applied - return the original.
     if (parent == null) {
       return noSuchFileException;
@@ -486,7 +491,12 @@ public final class EnsoFile implements EnsoObject {
       // On Linux, when creating a directory tree `foo/my-file.txt/a/b/c`, the operation fails with
       // `FileSystemException` with the full path (`foo/my-file.txt/a/b/c`). So we need to traverse
       // this path to find the actually problematic part.
-      var file = fromString(EnsoContext.get(null), path).truffleFile;
+      var file =
+          switch (fromString(EnsoContext.get(null), path)) {
+            case EnsoFile f -> f.truffleFile;
+            case null -> null;
+            default -> null;
+          };
       // We try to find the first file that exists on the path.
       while (file != null && !file.exists()) {
         file = file.getParent();
@@ -630,9 +640,17 @@ public final class EnsoFile implements EnsoObject {
       autoRegister = false)
   @Builtin.Specialize
   @TruffleBoundary
-  public static EnsoFile fromString(EnsoContext context, String path) {
-    TruffleFile file = context.getPublicTruffleFile(path);
-    return new EnsoFile(file);
+  public static EnsoObject fromString(EnsoContext context, String path)
+      throws IllegalArgumentException {
+    try {
+      TruffleFile file = context.getPublicTruffleFile(path);
+      return new EnsoFile(file);
+    } catch (IllegalArgumentException | UnsupportedOperationException ex) {
+      return context
+          .getBuiltins()
+          .error()
+          .makeUnsupportedArgumentsError(new Object[] {Text.create(path)}, ex.getMessage());
+    }
   }

   @Builtin.Method(
@@ -652,7 +670,7 @@ public final class EnsoFile implements EnsoObject {
       autoRegister = false)
   @Builtin.Specialize
   @TruffleBoundary
-  public static EnsoFile userHome(EnsoContext context) {
+  public static EnsoObject userHome(EnsoContext context) {
     return fromString(context, System.getProperty("user.home"));
   }

diff --git a/lib/java/test-utils/src/main/java/org/enso/test/utils/ProjectUtils.java b/lib/java/test-utils/src/main/java/org/enso/test/utils/ProjectUtils.java
index 878d0b663..b4abccba3 100644
--- a/lib/java/test-utils/src/main/java/org/enso/test/utils/ProjectUtils.java
+++ b/lib/java/test-utils/src/main/java/org/enso/test/utils/ProjectUtils.java
@@ -53,7 +53,8 @@ public class ProjectUtils {
 name: %s
 version: 0.0.1
 prefer-local-libraries: true
-        """.formatted(projName);
+        """
+            .formatted(projName);
     var yamlPath = projDir.resolve("package.yaml");
     Files.writeString(yamlPath, projYaml);
     assert yamlPath.toFile().exists();
diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java
index 17806a3d2..fde48a191 100644
--- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java
+++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java
@@ -126,7 +126,8 @@ public class BuiltinsProcessor extends AbstractProcessor {
               + "\")";
       out.println(builtinTypeAnnotation);
       out.println("public class " + builtinType.name() + " extends Builtin {");
-      out.println("""
+      out.println(
+          """
           @Override
           public boolean containsValues() {
         """);
diff --git a/test/Base_Tests/src/System/File_Spec.enso b/test/Base_Tests/src/System/File_Spec.enso
index d14eb3031..c7f54ed73 100644
--- a/test/Base_Tests/src/System/File_Spec.enso
+++ b/test/Base_Tests/src/System/File_Spec.enso
@@ -1,6 +1,7 @@
 from Standard.Base import all
 import Standard.Base.Errors.Common.Forbidden_Operation
 import Standard.Base.Errors.Common.Dry_Run_Operation
+import Standard.Base.Errors.Common.Unsupported_Argument_Types
 import Standard.Base.Errors.Encoding_Error.Encoding_Error
 import Standard.Base.Errors.File_Error.File_Error
 import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
@@ -41,6 +42,10 @@ add_specs suite_builder =
             path = sample_file.path
             File.new path

+        group_builder.specify "invalid char in path" <|
+            err = File.new "C:\dev:a"
+            err . should_fail_with Unsupported_Argument_Types
+
         group_builder.specify "should have `new` be a no-op on a file" <|
             file = File.new sample_file
             file . should_equal sample_file