apple/pkl · error · VmException

cannotEvaluateRelativeModuleUri

cannotEvaluateRelativeModuleUri

Error message

cannotEvaluateRelativeModuleUri

What it means

ModuleResolver.resolve throws cannotEvaluateRelativeModuleUri when given a ModuleSource whose URI is not absolute. Module resolution requires an absolute URI to match against registered ModuleKeyFactories; a relative URI has no scheme and cannot be dispatched. This is an internal-argument error: callers must pass ModuleSource with an absolute URI (or use text() to create a synthetic module).

Source

Thrown at pkl-core/src/main/java/org/pkl/core/runtime/ModuleResolver.java:44

import org.pkl.core.externalreader.ExternalReaderProcessException;
import org.pkl.core.module.ModuleKey;
import org.pkl.core.module.ModuleKeyFactory;
import org.pkl.core.module.ModuleKeys;

public final class ModuleResolver {
  private final Collection<ModuleKeyFactory> factories;

  public ModuleResolver(Collection<ModuleKeyFactory> factories) {
    this.factories = factories;
  }

  public Collection<ModuleKeyFactory> getFactories() {
    return factories;
  }

  public ModuleKey resolve(ModuleSource moduleSource) {
    if (!moduleSource.getUri().isAbsolute()) {
      throw new VmExceptionBuilder()
          .evalError("cannotEvaluateRelativeModuleUri", moduleSource.getUri())
          .build();
    }
    if (moduleSource.getContents() != null) {
      // `ModuleSource.text()` creates a synthetic module with URI `repl:text`, so it should be
      // matched to `ModuleKeys.synthetic`.
      if (moduleSource.getUri().equals(VmUtils.REPL_TEXT_URI)) {
        return ModuleKeys.synthetic(moduleSource.getUri(), moduleSource.getContents());
      }
      return resolveCached(moduleSource.getUri(), moduleSource.getContents());
    }
    return resolve(moduleSource.getUri());
  }

  public ModuleKey resolve(URI moduleUri) {
    return resolve(moduleUri, null);
  }

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Convert the relative path to an absolute URI before creating the ModuleSource (e.g. Path.toUri() or resolving against the importing module's URI).
  2. Use ModuleSource.text() if the content is synthetic, or file-based APIs that accept relative paths and resolve them for you.
  3. When using the CLI/Project APIs, let the built-in resolvers handle relative imports instead of calling ModuleResolver directly.

Example fix

// before
resolver.resolve(ModuleSource.get("config/template.pkl"));
// after
var abs = Paths.get("config/template.pkl").toAbsolutePath().toUri();
resolver.resolve(ModuleSource.get(abs.toString()));
Defensive patterns

Strategy: validation

Validate before calling

fun requireAbsoluteUri(src: ModuleSource) {
  require(src.uri.isAbsolute) { "ModuleSource URI must be absolute, got: ${src.uri}" }
}

Prevention

When it happens

Trigger: Calling ModuleResolver.resolve(ModuleSource) with a source built from a relative URI, e.g. ModuleSource.get("relative.pkl") instead of an absolute URI; also reached via resolveOutputPaths and various key-resolution helpers.

Common situations: Embedding Pkl and passing relative paths straight into resolve instead of resolving them against a base URI or the file system; constructing module sources manually in tests/tools.

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