apple/pkl · error · PklException

invalidRelativeProjectImport

invalidRelativeProjectImport

Error message

invalidRelativeProjectImport

What it means

Raised when a module imports a path starting with `/` (an absolute path) while the project's directory is not the filesystem root. Package validation forbids absolute-path imports because they cannot be resolved relative to the packaged project.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/project/ProjectPackager.java:451

    var imports = getImportsAndReads(pklModulePath);
    for (var importContext : imports) {
      var importStr = importContext.stringValue();
      var sourceSection = importContext.sourceSection();
      if (isAbsoluteImport(importStr)) {
        continue;
      }
      URI importUri;
      try {
        importUri = IoUtils.toUri(importStr);
      } catch (URISyntaxException e) {
        throw new VmExceptionBuilder()
            .evalError("invalidModuleUri", importStr)
            .withSourceSection(sourceSection)
            .build()
            .toPklException(stackFrameTransformer, color);
      }
      if (importStr.startsWith("/") && !project.getProjectDir().toString().equals("/")) {
        throw new VmExceptionBuilder()
            .evalError("invalidRelativeProjectImport", importStr)
            .withSourceSection(sourceSection)
            .build()
            .toPklException(stackFrameTransformer, color);
      }
      var currentPath = pklModulePath.getParent();
      assert currentPath != null;
      var importPath = importUri.getPath().split("/");
      // It's not good enough to just check the normalized path to see whether it exists within the
      // root dir.
      // It's possible that the import path resolves to a path outside the project dir,
      // and then back inside the project dir.
      for (var segment : importPath) {
        // replace any possibly reserved filename characters with underscore.
        currentPath = currentPath.resolve(sanitizePathSegment(segment));
        var normalized = currentPath.normalize();
        if (!normalized.startsWith(project.getProjectDir())) {
          throw new VmExceptionBuilder()

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Change the import to a project-relative path (e.g. import "foo/bar.pkl")
  2. Remove the leading slash from the import string
  3. If an external file is truly needed, declare it as a dependency instead

Example fix

// before
import "/shared/base.pkl"
// after
import "../shared/base.pkl"  // or a project-relative path
Defensive patterns

Strategy: validation

Validate before calling

// reject absolute import paths before packaging
if (importStr.startsWith("/")) throw new IllegalStateException("absolute import not allowed: " + importStr);

Try / catch

try { validatePklImportsAndReads(...) } catch (PklException e) { if (e.message.contains("invalidRelativeProjectImport")) showRelativeImportGuidance(e) else throw e }

Prevention

When it happens

Trigger: validateImportsAndReads sees an importStr beginning with "/" and project.getProjectDir() != "/" during `pkl project package` validation.

Common situations: Accidentally writing import "/foo/bar.pkl" instead of a relative path; copy-pasted absolute paths from local experiments into project sources.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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