apple/pkl · error · IllegalArgumentException

Expected absolute URI, but got:

Error message

Expected absolute URI, but got: 

What it means

IoUtils.toPath(URI) converts an absolute URI into a java.nio.file.Path. The library throws this IllegalArgumentException when the URI is relative (has no scheme), because a relative URI cannot denote a filesystem location.

Solutions

  1. Ensure the URI has a scheme before calling toPath, e.g. resolve it against a base: base.resolve(relativeUri)
  2. Check uri.isAbsolute() yourself and handle the relative case explicitly
  3. If the input should be a filesystem path, convert via Paths.get(String) instead of wrapping in a URI

Example fix

// before
Path p = IoUtils.toPath(URI.create("modules/foo.pkl"));
// after
URI u = URI.create("modules/foo.pkl");
Path p = u.isAbsolute() ? IoUtils.toPath(u) : IoUtils.toPath(baseDir.toUri().resolve(u));
Defensive patterns

Strategy: validation

Validate before calling

if (!uri.isAbsolute()) { uri = baseUri.resolve(uri); }
Path p = IoUtils.toPath(uri);

Type guard

function isAbsoluteUri(u) { return u != null && u.getScheme() != null; }

Try / catch

try { return IoUtils.toPath(uri); } catch (IllegalArgumentException e) { /* handle relative URI */ return null; }

Prevention

When it happens

Trigger: Calling IoUtils.toPath() with a URI whose isAbsolute() is false, e.g. URI created from 'foo/bar.pkl' or created via URI.create("relative/path") instead of a file: or other absolute scheme.

Common situations: Resolving imports against a relative path, forgetting to call baseUri.resolve(relative) before conversion, reading a URI from config where the scheme part was omitted.

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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/util/IoUtils.java:298

    var lastDot = path.lastIndexOf('.');
    return lastDot == -1 || lastDot < lastSep
        ? path.substring(lastSep + 1)
        : path.substring(lastSep + 1, lastDot);
  }

  public static String takeLastSegment(String name, char separator) {
    var lastSep = name.lastIndexOf(separator);
    return name.substring(lastSep + 1);
  }

  public static String dropLastSegment(String name, char separator) {
    var lastSep = name.lastIndexOf(separator);
    return lastSep == -1 ? name : name.substring(0, lastSep);
  }

  public static @Nullable Path toPath(URI uri) {
    if (!uri.isAbsolute()) {
      throw new IllegalArgumentException("Expected absolute URI, but got: " + uri);
    }

    try {
      return Path.of(uri);
    } catch (IllegalArgumentException | FileSystemNotFoundException e) {
      return null;
    }
  }

  private static String doInferModuleName(URI moduleUri) {
    var path = moduleUri.getPath();
    if (path == null) { // equivalent to `URI.isOpaque()`
      // convention: take last segment of dot-separated name
      // after stripping any colon-separated version number
      return takeLastSegment(dropLastSegment(moduleUri.getSchemeSpecificPart(), ':'), '.');
    }
    return getNameWithoutExtension(path);
  }

View on GitHub (pinned to f3efcbfc9b)