apple/pkl · error · URISyntaxException

cannotHaveRelativeFragment

cannotHaveRelativeFragment

Error message

cannotHaveRelativeFragment

What it means

PackageAssetUri requires the URI fragment to be an absolute path starting with '/' (the asset path within the package). When the fragment exists but does not begin with '/', the constructor throws URISyntaxException with message key cannotHaveRelativeFragment, including the offending fragment and URI in the message.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/packages/PackageAssetUri.java:69

    }
    this.packageUri = packageUri;
    this.assetPath = assetPath;
  }

  public PackageAssetUri(String uri) throws URISyntaxException {
    this(new URI(uri));
  }

  public PackageAssetUri(URI uri) throws URISyntaxException {
    this.uri = uri;
    this.packageUri = new PackageUri(uri);
    var fragment = uri.getFragment();
    if (fragment == null) {
      throw new URISyntaxException(
          uri.toString(), ErrorMessages.create("invalidUriMissingFragment", uri));
    }
    if (!fragment.startsWith("/")) {
      throw new URISyntaxException(
          uri.toString(), ErrorMessages.create("cannotHaveRelativeFragment", fragment, uri));
    }
    this.assetPath = fragment;
  }

  public URI getUri() {
    return uri;
  }

  public PackageUri getPackageUri() {
    return packageUri;
  }

  public String getAssetPath() {
    return assetPath;
  }

  public Version getVersion() {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Add the leading slash to the fragment: #/gen/file.pkl instead of #gen/file.pkl
  2. Normalize the asset path before building the URI (ensure it starts with '/')
  3. Check for path-joining code that strips the leading slash from the fragment

Example fix

// before
URI.create("package://example.com/pkg@1.0.0#gen/pkg.pkl")
// after
URI.create("package://example.com/pkg@1.0.0#/gen/pkg.pkl")
Defensive patterns

Strategy: validation

Validate before calling

boolean fragmentIsAbsolute(URI uri) {
  String f = uri.getFragment();
  return f != null && f.startsWith("/");
}

Type guard

static PackageAssetUri safeCreate(URI uri) throws URISyntaxException {
  String f = uri.getFragment();
  if (f == null || !f.startsWith("/")) throw new IllegalArgumentException("fragment must start with '/': " + uri);
  return new PackageAssetUri(uri);
}

Try / catch

try {
  var u = new PackageAssetUri(uri);
} catch (URISyntaxException e) {
  if (e.getReason().contains("relative fragment")) {
    log.error("Fragment must be an absolute path: " + e.getInput(), e);
  }
}

Prevention

When it happens

Trigger: Constructing new PackageAssetUri(URI) with a URI like package://host/pkg@1.0.0#gen/file.pkl — fragment "gen/file.pkl" lacks the leading slash.

Common situations: Hand-written imports where the author omitted the leading slash after #, or code that concatenated a relative path into the fragment instead of the canonical #/path form.

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