apple/pkl · error

cannotHaveRelativeImport

cannotHaveRelativeImport

Error message

cannotHaveRelativeImport ${moduleUri}

What it means

After resolution, if the resulting module URI is not absolute, the builder rejects the import: every loaded module must resolve to an absolute URI. A relative string that could not be resolved against the importing module's URI triggers this.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:3280

    } catch (SecurityManagerException | PackageLoadError e) {
      throw exceptionBuilder().withSourceSection(createSourceSection(ctx)).withCause(e).build();
    } catch (VmException e) {
      throw exceptionBuilder()
          .evalError(e.getMessage(), e.getMessageArguments())
          .withCause(e.getCause())
          .withHintBuilder(e.getHintBuilder())
          .withSourceSection(createSourceSection(ctx))
          .build();
    } catch (ExternalReaderProcessException e) {
      throw exceptionBuilder()
          .evalError("externalReaderFailure")
          .withCause(e.getCause())
          .withSourceSection(createSourceSection(ctx))
          .build();
    }

    if (!resolvedUri.isAbsolute()) {
      throw exceptionBuilder()
          .evalError("cannotHaveRelativeImport", moduleKey.getUri())
          .withSourceSection(createSourceSection(ctx))
          .build();
    }
    return resolvedUri;
  }

  private ConstLevel getConstLevel(int modifiers) {
    if (VmModifier.isConst(modifiers)) return ConstLevel.ALL;
    return symbolTable.getCurrentScope().getConstLevel();
  }

  private VmException missingLocalPropertyValue(TypeAnnotation typeAnn) {
    var stop = typeAnn.span().stopIndex();
    return exceptionBuilder()
        .evalError("missingLocalPropertyValue")
        .withSourceSection(source.createSection(stop + 1, 0))
        .build();

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Load the module from a concrete file/project so relative imports can resolve
  2. Rewrite the import as an absolute URI (file:///... or package://...)
  3. Pass an explicit base/module URI when using the embedding APIs

Example fix

// before (no base for relative import)
import "config/base.pkl"
// after
import "file:///opt/pkl/config/base.pkl"
Defensive patterns

Strategy: validation

Validate before calling

function resolvesAbsolute(base, ref) {
  try { return new URL(ref, base).href } catch { return null }
}

Prevention

When it happens

Trigger: An `import` with a relative path used in a context with no base URI to resolve against (e.g. module loaded from a string/stdin), leaving `resolvedUri` relative.

Common situations: Evaluating modules from stdin or in-memory where relative imports have no filesystem anchor; programmatic use of `pkl` APIs with a module source lacking a base.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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