apple/pkl · error · CliException
Output file conflict: `output.files` entry `"$pathSpec"` res
Error message
Output file conflict: `output.files` entry `"$pathSpec"` resolves to file path `$realPath`, which is a directory.
What it means
writeMultipleFileOutput checks each resolved output path before writing; this error means one of the `output.files` pathSpec entries resolves to an existing directory, so the CLI cannot write a file at that path and aborts with a conflict error.
Source
Thrown at pkl-cli/src/main/kotlin/org/pkl/cli/CliCommandRunner.kt:129
if (outputFiles.isEmpty()) return
val writtenFiles = mutableMapOf<Path, String>()
val outputDir = options.normalizedWorkingDir
if (outputDir.exists() && !outputDir.isDirectory()) {
throw CliException("Output path `$outputDir` exists and is not a directory.")
}
for ((pathSpec, fileOutput) in outputFiles) {
checkPathSpec(pathSpec)
val resolvedPath = outputDir.resolve(pathSpec).normalize()
val realPath = if (resolvedPath.exists()) resolvedPath.toRealPath() else resolvedPath
val previousOutput = writtenFiles[realPath]
if (previousOutput != null) {
throw CliException(
"Output file conflict: `output.files` entries `\"${previousOutput}\"` and `\"$pathSpec\"` resolve to the same file path `$realPath`."
)
}
if (realPath.isDirectory()) {
throw CliException(
"Output file conflict: `output.files` entry `\"$pathSpec\"` resolves to file path `$realPath`, which is a directory."
)
}
writtenFiles[realPath] = pathSpec
realPath.createParentDirectories()
realPath.writeBytes(fileOutput.bytes)
val displayPath =
if (Path.of(pathSpec).isAbsolute) pathSpec
else IoUtils.relativize(resolvedPath, currentWorkingDir).toString()
errStream.writeText(displayPath + IoUtils.getLineSeparator())
errStream.flush()
}
}
class SynthesizedRunCommand(
private val spec: CommandSpec,
private val runner: CliCommandRunner,
name: String? = null,View on GitHub (pinned to f3efcbfc9b)
Solutions
- Remove or rename the directory at the reported path, then re-run.
- Adjust the `output.files` pathSpec to a distinct file path that does not collide with an existing directory.
- Clean stale output directories between runs in CI scripts.
- Check placeholder substitution results — an empty/odd value can make a spec resolve to a directory.
Example fix
// before
["%{moduleName}"] = output // resolves to existing dir 'myapp'
// after
["%{moduleName}.json"] = output Defensive patterns
Strategy: validation
Validate before calling
import java.nio.file.*
val p = outputDir.resolve(pathSpec).normalize()
require(!Files.isDirectory(p)) { "pathSpec $pathSpec resolves to existing directory $p" } Try / catch
try {
runner.writeMultipleFileOutput(outputFiles)
} catch (e: CliException) {
// clean conflicting paths reported in e.message, then retry
} Prevention
- Clean stale output directories between runs.
- Ensure pathSpec patterns always yield file paths (append extension), not bare module names.
- Keep single-file and multi-file outputs in separate directory trees.
When it happens
Trigger: An `output.files` pathSpec (after placeholder substitution and path resolution against the output dir) matches an existing directory — e.g. pattern `"%{moduleName}"` where a directory with that name exists, or a previously-created directory layout left behind by another run.
Common situations: Reusing an output directory where a prior run created subdirectories; pathSpec patterns ending up empty so the spec resolves to the output dir itself; collisions between file output names and multi-file-output subdirectories.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Output file conflict: `output.files` entries `"${previousOut
- Output path `$outputDir` exists and is not a directory.
- Output file `$outputFile` is a directory. Did you mean `--mu
- Output path `$outputDir` exists and is not a directory.
- Failed to write to $depsFile: ${e.message}
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/0ab4fcb0296202aa.
Report an issue: GitHub.