{"record":{"id":"06885a00a50c09a6","repo":"gradle/gradle","slug":"unable-to-create-test-kit-directory","errorCode":null,"errorMessage":"Unable to create test kit directory: {}","messagePattern":"Unable to create test kit directory: (.+?)","errorType":"exception","errorClass":"InvalidRunnerConfigurationException","httpStatus":null,"severity":"error","filePath":"platforms/extensibility/test-kit/src/main/java/org/gradle/testkit/runner/internal/DefaultGradleRunner.java","lineNumber":399,"sourceCode":"            execResult.getOutputSource(),\n            execResult.getTasks(),\n            execResult.getConfigurationCacheOutcome()\n        );\n    }\n\n    private File createTestKitDir(TestKitDirProvider testKitDirProvider) {\n        File dir = testKitDirProvider.getDir();\n        if (dir.isDirectory()) {\n            if (!dir.canWrite()) {\n                throw new InvalidRunnerConfigurationException(\"Unable to write to test kit directory: \" + dir.getAbsolutePath());\n            }\n            return dir;\n        } else if (dir.exists() && !dir.isDirectory()) {\n            throw new InvalidRunnerConfigurationException(\"Unable to use non-directory as test kit directory: \" + dir.getAbsolutePath());\n        } else if (dir.mkdirs() || dir.isDirectory()) {\n            return dir;\n        } else {\n            throw new InvalidRunnerConfigurationException(\"Unable to create test kit directory: \" + dir.getAbsolutePath());\n        }\n    }\n\n    private static GradleProvider findGradleInstallFromGradleRunner() {\n        GradleInstallation gradleInstallation = CurrentGradleInstallation.get();\n        if (gradleInstallation == null) {\n            String messagePrefix = \"Could not find a Gradle installation to use based on the location of the GradleRunner class\";\n            try {\n                File classpathForClass = ClasspathUtil.getClasspathForClass(GradleRunner.class);\n                messagePrefix += \": \" + classpathForClass.getAbsolutePath();\n            } catch (Exception ignore) {\n                // ignore\n            }\n            throw new InvalidRunnerConfigurationException(messagePrefix + \". Please specify a Gradle runtime to use via GradleRunner.withGradleVersion() or similar.\");\n        }\n        return GradleProvider.installation(gradleInstallation.getGradleHome());\n    }\n","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/extensibility/test-kit/src/main/java/org/gradle/testkit/runner/internal/DefaultGradleRunner.java#L381-L417","documentation":"Gradle TestKit needs a scratch directory (the \"test kit dir\") to store daemon logs and helper jars before it can launch a test build. DefaultGradleRunner.createTestKitDir() reuses the directory if it exists and is writable, rejects a non-directory path, and only as a last resort calls dir.mkdirs(). This InvalidRunnerConfigurationException means the directory does not exist and the filesystem refused to create it (mkdirs() failed and a follow-up isDirectory() check also failed).","triggerScenarios":"Running GradleRunner.build() with a test kit dir (default GRADLE_USER_HOME-based location, the TEST_KIT_DIR env var, or a dir passed via withTestKitDir(...)) that cannot be created: a parent path component is a regular file, the user lacks write permission on a parent directory, the volume is read-only, or the disk is full.","commonSituations":"CI containers with a read-only or non-writable GRADLE_USER_HOME; a stray regular file occupying a parent path such as ~/.gradle/test-kit; Docker read-only mounts or macOS sandboxing; full build-agent disks.","solutions":["Check the path printed in the message: verify every parent directory exists, is a directory, and is writable; confirm no regular file sits in the path","Fix the environment: free disk space (df -h), remount the volume read-write, or chmod the parent directory","Point TestKit somewhere writable: GradleRunner.create().withTestKitDir(new File(System.getProperty(\"java.io.tmpdir\"), \"test-kit\"))","If a stale file or lock occupies the dir, remove it: rm -rf <dir> and rerun the test"],"exampleFix":"// before\nGradleRunner.create()\n    .withProjectDir(projectDir)\n    .withArguments(\"build\")\n    .build(); // fails when the default test-kit dir cannot be created\n\n// after\nGradleRunner.create()\n    .withProjectDir(projectDir)\n    .withTestKitDir(new File(System.getProperty(\"java.io.tmpdir\"), \"my-test-kit\"))\n    .withArguments(\"build\")\n    .build();","handlingStrategy":"validation","validationCode":"File testKitDir = new File(System.getProperty(\"user.home\"), \".gradle/test-kit\");\nif (testKitDir.isDirectory() && !testKitDir.canWrite()) {\n    throw new IllegalStateException(\"Test kit dir not writable: \" + testKitDir);\n}\nFile probe = testKitDir;\nwhile (probe != null && !probe.exists()) { probe = probe.getParentFile(); }\nif (probe != null && !probe.isDirectory()) {\n    throw new IllegalStateException(\"A non-directory blocks the path: \" + probe);\n}\nif (!testKitDir.exists() && !testKitDir.mkdirs()) {\n    throw new IllegalStateException(\"Cannot create test kit dir: \" + testKitDir);\n}","typeGuard":null,"tryCatchPattern":"try {\n    runner.build();\n} catch (InvalidRunnerConfigurationException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unable to create test kit directory\")) {\n        runner = runner.withTestKitDir(new File(System.getProperty(\"java.io.tmpdir\"), \"test-kit\"));\n        runner.build(); // retry once with a known-writable dir\n    } else {\n        throw e;\n    }\n}","preventionTips":["Call withTestKitDir(...) with a directory you verified is creatable in CI","Grant write access to GRADLE_USER_HOME on build agents","Add a @BeforeAll canWrite()/mkdirs() pre-flight check to TestKit-based test suites","Keep Docker mounts for the Gradle user home read-write"],"tags":["gradle","testkit","filesystem","permissions","mkdir"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}