{"record":{"id":"f3a190b682064503","repo":"apple/pkl","slug":"cannothaverelativefragment","errorCode":"cannotHaveRelativeFragment","errorMessage":"cannotHaveRelativeFragment","messagePattern":"cannotHaveRelativeFragment","errorType":"error_code","errorClass":"URISyntaxException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/packages/PackageAssetUri.java","lineNumber":69,"sourceCode":"    }\n    this.packageUri = packageUri;\n    this.assetPath = assetPath;\n  }\n\n  public PackageAssetUri(String uri) throws URISyntaxException {\n    this(new URI(uri));\n  }\n\n  public PackageAssetUri(URI uri) throws URISyntaxException {\n    this.uri = uri;\n    this.packageUri = new PackageUri(uri);\n    var fragment = uri.getFragment();\n    if (fragment == null) {\n      throw new URISyntaxException(\n          uri.toString(), ErrorMessages.create(\"invalidUriMissingFragment\", uri));\n    }\n    if (!fragment.startsWith(\"/\")) {\n      throw new URISyntaxException(\n          uri.toString(), ErrorMessages.create(\"cannotHaveRelativeFragment\", fragment, uri));\n    }\n    this.assetPath = fragment;\n  }\n\n  public URI getUri() {\n    return uri;\n  }\n\n  public PackageUri getPackageUri() {\n    return packageUri;\n  }\n\n  public String getAssetPath() {\n    return assetPath;\n  }\n\n  public Version getVersion() {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/packages/PackageAssetUri.java#L51-L87","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add the leading slash to the fragment: #/gen/file.pkl instead of #gen/file.pkl","Normalize the asset path before building the URI (ensure it starts with '/')","Check for path-joining code that strips the leading slash from the fragment"],"exampleFix":"// before\nURI.create(\"package://example.com/pkg@1.0.0#gen/pkg.pkl\")\n// after\nURI.create(\"package://example.com/pkg@1.0.0#/gen/pkg.pkl\")","handlingStrategy":"validation","validationCode":"boolean fragmentIsAbsolute(URI uri) {\n  String f = uri.getFragment();\n  return f != null && f.startsWith(\"/\");\n}","typeGuard":"static PackageAssetUri safeCreate(URI uri) throws URISyntaxException {\n  String f = uri.getFragment();\n  if (f == null || !f.startsWith(\"/\")) throw new IllegalArgumentException(\"fragment must start with '/': \" + uri);\n  return new PackageAssetUri(uri);\n}","tryCatchPattern":"try {\n  var u = new PackageAssetUri(uri);\n} catch (URISyntaxException e) {\n  if (e.getReason().contains(\"relative fragment\")) {\n    log.error(\"Fragment must be an absolute path: \" + e.getInput(), e);\n  }\n}","preventionTips":["Ensure fragments are absolute asset paths: #/file.pkl, never #file.pkl","Normalize paths to start with '/' before building the fragment","Add a unit test for PackageAssetUri construction with typical import strings"],"tags":["pkl","uri","fragment"],"backgroundTag":"invalid-url-format","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}