apple/pkl · error · VmException

cannotFindModule

cannotFindModule

Error message

cannotFindModule

What it means

ModuleCache.resolve throws cannotFindModule when a module URI (typically a relative/path or unregistered scheme import) cannot be resolved or loaded by any registered module key factory; the module file does not exist at the resolved location or no factory can handle the URI. If the path contains backslashes, a hint about using `/` as directory separator is attached. IOExceptions during loading surface separately as ioErrorLoadingModule.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/runtime/ModuleCache.java:217

  private ResolvedModuleKey resolve(
      ModuleKey module, SecurityManager securityManager, @Nullable Node importNode) {
    try {
      return module.resolve(securityManager);
    } catch (SecurityManagerException | PackageLoadError | HttpClientException e) {
      throw new VmExceptionBuilder().withOptionalLocation(importNode).withCause(e).build();
    } catch (FileNotFoundException | NoSuchFileException e) {
      var exceptionBuilder =
          new VmExceptionBuilder()
              .withOptionalLocation(importNode)
              .evalError("cannotFindModule", module.getUri());
      var path = module.getUri().getPath();
      if (path != null && path.contains("\\")) {
        exceptionBuilder.withHint(
            "To resolve modules in nested directories, use `/` as the directory separator.");
      }
      throw exceptionBuilder.build();
    } catch (IOException e) {
      throw new VmExceptionBuilder()
          .withOptionalLocation(importNode)
          .evalError("ioErrorLoadingModule", module.getUri())
          .withCause(e)
          .build();
    }
  }
}

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Fix the import path (check spelling and that the file exists relative to the importing module).
  2. Replace backslashes with forward slashes if the path contains `\`.
  3. Register the appropriate ModuleKeyFactory/module path mapping if using a custom scheme or embedded resolver.

Example fix

// before
import "configs\settings.pkl"
// after
import "configs/settings.pkl"
Defensive patterns

Strategy: validation

Validate before calling

fun assertImportable(importerPath: Path, importPath: String) {
  require('\\' !in importPath) { "use '/' as directory separator" }
  val resolved = importerPath.toAbsolutePath().parent!!.resolve(importPath).normalize()
  require(java.nio.file.Files.exists(resolved)) { "module not found: $resolved" }
}

Prevention

When it happens

Trigger: `import "relative/path/to.pkl"` where the file does not exist; importing a module via a scheme with no registered ModuleKeyFactory; Windows-style backslash paths pasted into imports.

Common situations: Wrong working directory when evaluating; missing files in a project layout; typos in module paths; moving modules without updating imports; running on Windows with `\` separators in import strings.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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