native-build-tools icon indicating copy to clipboard operation
native-build-tools copied to clipboard

[Native Image] Error > 'other' has different root when building

Open duykhongphai opened this issue 5 months ago • 4 comments

Describe the Issue I’m not sure why this happens, but I installed GraalVM JDK on the C drive and set both JAVA_HOME and GRAALVM_HOME to the full installation path. I also verified that the native-image tool is available on all drives. However, the issue is that I can only build native images on the C drive. When I try to build on a different drive (like D or E), I get the following error: *** What went wrong: Execution failed for task ':nativeCompile'. 'other' has different root**

plugins {
    id 'java'
    id 'org.graalvm.buildtools.native' version '0.11.0'
}

group = 'org.test'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation platform('org.junit:junit-bom:5.10.0')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}

test {
    useJUnitPlatform()
}

graalvmNative {
    binaries {
        main {
            imageName     = 'application'
            mainClass     = 'org.test.Main'
            debug         = true
            verbose       = true
            fallback      = true
            sharedLibrary = false
            quickBuild    = false
            richOutput    = false
        }
    }
}
Image

duykhongphai avatar Jul 26 '25 11:07 duykhongphai

Stacktrace is this:

Caused by: java.lang.IllegalArgumentException: 'other' has different root
	at org.graalvm.buildtools.utils.NativeImageUtils.convertToArgsFile(NativeImageUtils.java:104)
	at org.graalvm.buildtools.gradle.internal.NativeImageCommandLineProvider.asArguments(NativeImageCommandLineProvider.java:238)
	at org.graalvm.buildtools.gradle.tasks.BuildNativeImageTask.buildActualCommandLineArgs(BuildNativeImageTask.java:277)
	at org.graalvm.buildtools.gradle.tasks.BuildNativeImageTask.exec(BuildNativeImageTask.java:306)

You can temporarily set something like this in you global gradle.properties or via the environment:

org.gradle.jvmargs=-Djava.io.tmpdir=D:/Temp

It happens when your project and temp folder are on different drives.

megla-tlanghorst avatar Aug 07 '25 08:08 megla-tlanghorst

Same here, I'm on windows, after moving my project to C drive the issue is gone. But it is not a good solution at all.
As I search on web, found that android studio used to have this error when generating apk files if a "destination path" setting is not set properly. I wonder if graalvm's gradle plugin can provide similar setting for nativeCompile task.

Paper-Folding avatar Aug 31 '25 07:08 Paper-Folding

For me it is happening on GitHub Action runners since I don't have a windows box or VM at home.

Also, my versions: Gradle 9.1, build tools 0.11.2

exception
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':jufmt-cli:nativeCompile'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:135)
	at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:288)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:133)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:121)
	at org.gradle.api.internal.tasks.execution.ProblemsTaskPathTrackingTaskExecuter.execute(ProblemsTaskPathTrackingTaskExecuter.java:41)
	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
Caused by: java.lang.IllegalArgumentException: 'other' has different root
	at org.graalvm.buildtools.utils.NativeImageUtils.convertToArgsFile(NativeImageUtils.java:104)
	at org.graalvm.buildtools.gradle.internal.NativeImageCommandLineProvider.asArguments(NativeImageCommandLineProvider.java:238)
	at org.graalvm.buildtools.gradle.tasks.BuildNativeImageTask.buildActualCommandLineArgs(BuildNativeImageTask.java:277)
	at org.graalvm.buildtools.gradle.tasks.BuildNativeImageTask.exec(BuildNativeImageTask.java:306)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:125)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
	at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:252)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
	at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:237)
	at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:220)
	at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:203)
	at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:170)
	at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:105)
	at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:44)
	at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:59)
	at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:56)
	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:44)
	at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:42)
	at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:75)
	at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
	at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:50)
	at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:28)

Thanks to the original report, I looked at the post setup step and noticed that multiple drives are at play:

The daemon is running on D and my repo was checked out on D as well:

  Stopping Gradle daemons for D:\a\.gradle\wrapper\dists\gradle-9.1.0-bin\9agqghryom9wkf8r80qlhnts3\gradle-9.1.0
  C:\Windows\system32\cmd.exe /D /S /C "D:\a\.gradle\wrapper\dists\gradle-9.1.0-bin\9agqghryom9wkf8r80qlhnts3\gradle-9.1.0\bin\gradle.bat --stop"
Initializing the repository
  "C:\Program Files\Git\bin\git.exe" init D:\a\jufmt\jufmt

The toolchain is however on C:

  env:
    GRAALVM_HOME: C:\hostedtoolcache\windows\graalvm-community-jdk-25.0.1_windows-x64_bin\25.0.1\x64\graalvm-community-openjdk-25.0.1+8.1
    JAVA_HOME: C:\hostedtoolcache\windows\graalvm-community-jdk-25.0.1_windows-x64_bin\25.0.1\x64\graalvm-community-openjdk-25.0.1+8.1
    NATIVE_IMAGE_OPTIONS: -H:BuildOutputJSONFile=C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\native-image-build-output.json

The task a hand:

named<BuildNativeImageTask>("nativeCompile") {
    classpathJar.fileProvider(shadowJar.map { it.archiveFile.get().asFile })
}

So, the error looks like the plugin tries to create an args file in a temp location, but it cannot relativize paths from different root (here C and D).

Thanks to @megla-tlanghorst's comment, I applied the same fix, but only in my GHA workflow:

 - name: Build native image
   run: ./gradlew nativeCompile --stacktrace
+  env:
+    # Needed for Windows; to resolve issue with temp folder during native image build, due to relativization
+    # problem when different drives are used, such as in GHA runners.
+    # https://github.com/graalvm/native-build-tools/issues/754
+    GRADLE_OPTS: -Djava.io.tmpdir=${{ runner.temp }}

On Windows GHA runners, the runner.temp will use the temp location of the "attached" drive, e.g. D:\a\_temp.

More doc : https://docs.github.com/en/actions/reference/workflows-and-actions/contexts

bric3 avatar Oct 27 '25 11:10 bric3

@melix mentioned in https://github.com/oracle/graal/issues/11795#issuecomment-3415849736

This is caused by https://github.com/graalvm/native-build-tools/blob/a5cd92d30aab3bdb50033b85f5f7a08c955cf871/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/NativeImageCommandLineProvider.java#L236-L239 so this issue should probably be moved to NBT.

wirthi avatar Nov 04 '25 10:11 wirthi