apple/pkl · error · VmException

cannotFindResource

cannotFindResource

Error message

Cannot find resource `{0}`.

What it means

Pkl throws this when a resource URI parsed successfully but IoUtils.resolve, which resolves the URI relative to the current module key through the security manager, reports that the target resource does not exist (FileNotFoundException). The resource simply cannot be located at the resolved location.

Solutions

  1. Verify the file/resource exists at the resolved location; print the URI to confirm where it resolves relative to the module.
  2. Fix relative paths — remember they resolve against the module's location, not the working directory.
  3. Check filename spelling and case, especially on Linux CI.
  4. If the resource comes from a package, ensure the package is loaded and actually contains the resource.

Example fix

// before
read("confg.json")
// after
read("config.json")
Defensive patterns

Strategy: validation

Validate before calling

// Before evaluating, check the resource exists relative to the module file
// host side (Java/Kotlin):
//   java.nio.file.Files.exists(Path.of(moduleDir, resourcePath))

Prevention

When it happens

Trigger: Calling `read()` with a URI whose resolved target file/endpoint does not exist: wrong relative path from the module, misspelled filename, or a deleted/moved file.

Common situations: Typo in a file path relative to the module; resource lives in a different directory than assumed; CI environment lacks the file; path casing differs on case-sensitive filesystems.

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/d3650b7b13a5c767. Report an issue: GitHub.

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/unary/AbstractReadNode.java:66

          .withHint(e.getReason())
          .build();
    }
  }

  @TruffleBoundary
  protected final @Nullable Object doRead(String resourceUri, VmContext context, Node readNode) {
    var resolvedUri = resolveResource(currentModule, resourceUri);
    return context.getResourceManager().read(resolvedUri, readNode).orElse(null);
  }

  private URI resolveResource(ModuleKey moduleKey, String resourceUri) {
    var parsedUri = parseUri(resourceUri);
    var context = VmContext.get(this);
    URI resolvedUri;
    try {
      resolvedUri = IoUtils.resolve(context.getSecurityManager(), moduleKey, parsedUri);
    } catch (FileNotFoundException e) {
      throw exceptionBuilder().evalError("cannotFindResource", resourceUri).build();
    } catch (URISyntaxException e) {
      throw exceptionBuilder()
          .evalError("invalidResourceUri", resourceUri)
          .withHint(e.getReason())
          .build();
    } catch (IOException e) {
      throw exceptionBuilder()
          .evalError("ioErrorReadingResource", resourceUri)
          .withHint(e.getMessage())
          .build();
    } catch (PackageLoadError | SecurityManagerException e) {
      throw exceptionBuilder().withCause(e).build();
    } catch (ExternalReaderProcessException e) {
      throw exceptionBuilder().evalError("externalReaderFailure").withCause(e).build();
    }

    if (!resolvedUri.isAbsolute()) {
      throw exceptionBuilder().evalError("cannotHaveRelativeResource", moduleKey.getUri()).build();

View on GitHub (pinned to f3efcbfc9b)