apple/pkl · error · ExecutorException

I/O error loading Pkl module `%s`.

Error message

I/O error loading Pkl module `%s`.

What it means

detectRequestedPklVersion reads the module file as UTF-8 to extract its @ModuleInfo minPklVersion. If Files.readString throws IOException, evaluatePath aborts with ExecutorException "I/O error loading Pkl module". The original IOException is attached as the cause.

Source

Thrown at pkl-executor/src/main/java/org/pkl/executor/EmbeddedExecutor.java:113

      @Nullable Version requestedVersion,
      @Nullable PklDistribution distribution,
      long startTime,
      long endTime) {
    logger.info(
        "Finished evaluating Pkl module. modulePath={} outcome={} requestedVersion={} selectedVersion={} elapsedMillis={}",
        modulePath,
        success,
        requestedVersion == null ? "n/a" : requestedVersion.toString(),
        distribution == null ? "n/a" : distribution.getVersion().toString(),
        (endTime - startTime) / 1_000_000);
  }

  private Version detectRequestedPklVersion(Path modulePath, ExecutorOptions options) {
    String sourceText;
    try {
      sourceText = Files.readString(modulePath, StandardCharsets.UTF_8);
    } catch (IOException e) {
      throw new ExecutorException(
          String.format("I/O error loading Pkl module `%s`.", toDisplayPath(modulePath, options)),
          e);
    }

    var version = extractMinPklVersion(sourceText);
    if (version != null) return version;

    var availableVersions =
        pklDistributions.stream()
            .map(it -> it.getVersion().toString())
            .collect(Collectors.joining(", "));

    throw new ExecutorException(
        String.format(
            "Pkl module `%s` does not state which Pkl version it requires. (Available versions: %s)%n"
                + "To fix this problem, annotate the module's `amends`, `extends`, or `module` clause with `@ModuleInfo { minPklVersion = \"x.y.z\" }`.",
            toDisplayPath(modulePath, options), availableVersions));
  }

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Check file read permissions for the process user (chmod / run as the right user)
  2. Confirm the file still exists and is on a healthy filesystem at read time
  3. Retry on transient I/O errors if the file is on a network mount
  4. Inspect the cause (getCause()) for the underlying IOException detail

Example fix

// before
executor.evaluatePath(path, options); // may throw opaque IO error
// after
if (!Files.isReadable(path)) throw new IllegalStateException("not readable: " + path);
try { executor.evaluatePath(path, options); }
catch (ExecutorException e) { log.error("module load failed", e.getCause()); throw e; }
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Files.isReadable(path)) throw new IllegalStateException("module not readable: " + path);

Type guard

boolean isReadableFile(Path p) { return Files.isRegularFile(p) && Files.isReadable(p); }

Try / catch

try { executor.evaluatePath(p, options); } catch (ExecutorException e) { if (e.getCause() instanceof IOException io) throw new ModuleLoadException(p, io); throw e; }

Prevention

When it happens

Trigger: The file existed at the existence check but could not be read as UTF-8 text: permission denied, file deleted between checks (race), I/O error on a network/NFS mount, or encoding issues surfaced as an IO failure.

Common situations: Files readable to one user but not the executor's user; modules on removable/network drives; TOCTOU races where the file is removed between the isRegularFile check and readString.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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