{"record":{"id":"4f7d7ffe4ba161eb","repo":"apple/pkl","slug":"output-path-outputdir-exists-and-is-not-a-direc-4f7d7f","errorCode":null,"errorMessage":"Output path `$outputDir` exists and is not a directory.","messagePattern":"Output path `\\$outputDir` exists and is not a directory\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"pkl-cli/src/main/kotlin/org/pkl/cli/CliEvaluator.kt","lineNumber":235,"sourceCode":"\n  private fun toModuleSource(uri: URI, reader: InputStream) =\n    if (uri == VmUtils.REPL_TEXT_URI) {\n      ModuleSource.create(uri, reader.readAllBytes().toString(StandardCharsets.UTF_8))\n    } else {\n      ModuleSource.uri(uri)\n    }\n\n  /**\n   * Renders each module's `output.files`, writing each entry as a file into the specified output\n   * directory.\n   */\n  private fun writeMultipleFileOutput(builder: EvaluatorBuilder) {\n    val outputDirs = directoryOutputPaths!!\n    val writtenFiles = mutableMapOf<Path, OutputFile>()\n    builder.setOutputFormat(options.outputFormat).build().use { evaluator ->\n      for ((moduleUri, outputDir) in outputDirs) {\n        if (outputDir.exists() && !outputDir.isDirectory()) {\n          throw CliException(\"Output path `$outputDir` exists and is not a directory.\")\n        }\n        val moduleSource = toModuleSource(moduleUri, inputStream)\n        val output = evaluator.evaluateOutputFiles(moduleSource)\n        val realOutputDir = if (outputDir.exists()) outputDir.toRealPath() else outputDir\n\n        for ((pathSpec, fileOutput) in output) {\n          checkPathSpec(pathSpec)\n          val (realPath, resolvedPath) = realOutputDir.resolveRealPath(Path.of(pathSpec))\n          if (!realPath.startsWith(realOutputDir)) {\n            throw CliException(\n              \"Output file conflict: `output.files` entry `\\\"$pathSpec\\\"` in module `$moduleUri` resolves to file path `$realPath`, which is outside output directory `$realOutputDir`.\"\n            )\n          }\n          val previousOutput = writtenFiles[realPath]\n          if (previousOutput != null) {\n            throw CliException(\n              \"Output file conflict: `output.files` entries `\\\"${previousOutput.pathSpec}\\\"` in module `${previousOutput.moduleUri}` and `\\\"$pathSpec\\\"` in module `$moduleUri` resolve to the same file path `$realPath`.\"\n            )","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-cli/src/main/kotlin/org/pkl/cli/CliEvaluator.kt#L217-L253","documentation":"In multiple-file output mode, CliEvaluator.writeMultipleFileOutput validates each per-module output directory: if the target directory path exists but is not a directory (e.g. a regular file), it throws CliException because file outputs cannot be placed there.","triggerScenarios":"Running pkl with --multiple-file-output-path(s) where one of the resolved directory output paths exists as a regular file — commonly a leftover single-file output or a wrong flag value.","commonSituations":"Previous runs wrote a file at the path now used as the multi-file output dir; CI caches a stale file; a typo merges the output dir path with a filename.","solutions":["Delete or move the existing file at the reported outputDir path so a directory can be created.","Verify the --multiple-file-output-path argument points to a directory location.","Add cleanup (`rm -f <path>` or equivalent) to scripts before multi-file output runs.","Separate single-file and multi-file output locations to avoid collisions."],"exampleFix":"# before\n$ pkl eval -m build/out ...   # build/out is a stale file\n# after\n$ rm build/out && mkdir -p build/out && pkl eval -m build/out ...","handlingStrategy":"validation","validationCode":"import java.nio.file.Files\nimport java.nio.file.Path\nfor ((_, dir) in outputDirs) {\n  require(!Files.exists(dir) || Files.isDirectory(dir)) { \"Output path $dir exists and is not a directory\" }\n}","typeGuard":null,"tryCatchPattern":"try {\n  ev.writeMultipleFileOutput(builder)\n} catch (e: CliException) {\n  System.err.println(e.message)\n}","preventionTips":["Ensure each --multiple-file-output-path target is absent or a directory before running.","Add pre-run cleanup of stale outputs in CI pipelines.","Keep single-file and multi-file output locations separate."],"tags":["cli","output-path","filesystem"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}