apple/pkl · error · CliException

I/O error writing file `$outputFile`. Cause: ${e.message}

Error message

I/O error writing file `$outputFile`.
Cause: ${e.message}

What it means

Thrown by CliJavaCodeGenerator.doRun when an IOException occurs while writing a generated Java source file to disk. The CLI wraps the underlying IOException into a CliException so the command fails with a clear message identifying the output file. It indicates a filesystem-level failure (permissions, disk space, path issues), not a code-generation problem.

Source

Thrown at pkl-codegen-java/src/main/kotlin/org/pkl/codegen/java/CliJavaCodeGenerator.kt:43

/** API for the Java code generator CLI. */
class CliJavaCodeGenerator(private val options: CliJavaCodeGeneratorOptions) :
  CliCommand(options.base) {

  override fun doRun() {
    val builder = evaluatorBuilder()
    try {
      builder.build().use { evaluator ->
        for (moduleUri in options.base.normalizedSourceModules) {
          val schema = evaluator.evaluateSchema(ModuleSource.uri(moduleUri))
          val codeGenerator = JavaCodeGenerator(schema, options.toJavaCodeGeneratorOptions())
          try {
            for ((fileName, fileContents) in codeGenerator.output) {
              val outputFile = options.outputDir.resolve(fileName)
              try {
                outputFile.createParentDirectories().writeString(fileContents)
              } catch (e: IOException) {
                throw CliException("I/O error writing file `$outputFile`.\nCause: ${e.message}")
              }
            }
          } catch (e: JavaCodeGeneratorException) {
            throw CliException(e.message!!)
          }
        }
      }
    } finally {
      Closeables.closeQuietly(builder.moduleKeyFactories)
      Closeables.closeQuietly(builder.resourceReaders)
    }
  }
}

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Check that the --output-dir exists and is writable by the current user (ls -ld, touch a test file).
  2. Free up disk space / check quota if the disk is full.
  3. Ensure no file at the target path is locked or is a directory; close editors/AV that hold the file open.
  4. Run the command with appropriate permissions or fix ownership of the output directory.
  5. Use a different output directory to isolate whether the path is the problem.

Example fix

// before (CI failing on read-only dir)
pkl gen java --output-dir /srv/app/generated module.pkl
// after
pkl gen java --output-dir "$PWD/generated" module.pkl
Defensive patterns

Strategy: try-catch

Validate before calling

val out = File(outputDir); require(out.canWrite()) { "output dir not writable: $out" }

Type guard

fun isWritableDir(path: Path): Boolean = Files.isDirectory(path) && Files.isWritable(path)

Try / catch

try { runGenerator() } catch (e: CliException) { if (e.message?.startsWith("I/O error writing file") == true) { /* check disk/permissions, retry or fail fast */ } else throw e }

Prevention

When it happens

Trigger: Calling the Java codegen CLI with --output-dir pointing to a non-writable or non-existent path, a path that is a directory with the same name as a target file, or a disk that is full; outputFile.createParentDirectories().writeString(fileContents) throws IOException.

Common situations: Running in CI with read-only workspace, output dir owned by another user, Windows file locked by an IDE/editor, disk quota exceeded, or outputDir resolving onto a read-only mount.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/942f0dfddc9631a1. Report an issue: GitHub.