{"record":{"id":"a37e5d6d970e4478","repo":"apple/pkl","slug":"failed-to-parse-pkl-module-uri-s","errorCode":null,"errorMessage":"Failed to parse Pkl module URI: ${s}","messagePattern":"Failed to parse Pkl module URI: (.+?)","errorType":"validation","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"pkl-gradle/src/main/java/org/pkl/gradle/utils/PluginUtils.java","lineNumber":97,"sourceCode":"    } else if (notation instanceof Path path) {\n      try {\n        return path.toFile();\n      } catch (UnsupportedOperationException e) {\n        throw new InvalidUserDataException(\"Failed to parse Pkl module file path: \" + notation, e);\n      }\n    } else if (notation instanceof URL url) {\n      try {\n        return parseModuleNotation(url.toURI());\n      } catch (URISyntaxException e) {\n        throw new InvalidUserDataException(\"Failed to parse Pkl module URI: \" + notation, e);\n      }\n    } else if (notation instanceof CharSequence) {\n      var s = notation.toString();\n      if (IoUtils.isUriLike(s)) {\n        try {\n          return parseModuleNotation(IoUtils.toUri(s));\n        } catch (URISyntaxException e) {\n          throw new InvalidUserDataException(\"Failed to parse Pkl module URI: \" + s, e);\n        }\n      } else {\n        try {\n          return Paths.get(s).toFile();\n        } catch (InvalidPathException | UnsupportedOperationException e) {\n          throw new InvalidUserDataException(\"Failed to parse Pkl module file path: \" + s, e);\n        }\n      }\n    } else if (notation instanceof FileSystemLocation location) {\n      return location.getAsFile();\n    } else {\n      throw new InvalidUserDataException(\n          \"Unsupported value of type \"\n              + notation.getClass()\n              + \" used as a module path: \"\n              + notation);\n    }\n  }","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-gradle/src/main/java/org/pkl/gradle/utils/PluginUtils.java#L79-L115","documentation":"For String notations that look URI-like, parseModuleNotation converts the string with IoUtils.toUri(); a URISyntaxException is wrapped in InvalidUserDataException \"Failed to parse Pkl module URI: <s>\". It lets malformed URI strings (bad scheme, illegal characters) fail with a clear message rather than obscure CLI errors later.","triggerScenarios":"Passing a module string containing \"://\" or otherwise URI-like but syntactically invalid (e.g. \"pkl://a b/mod.pkl\", \"https:/missing-host\", unescaped spaces or brackets) to pkl Gradle module configuration.","commonSituations":"Typos in remote module URIs (single slash after scheme); interpolating unencoded paths with spaces into https/file URIs; copying URIs with curly quotes or trailing characters from docs; env-specific values injected unescaped.","solutions":["Fix the URI string to a valid RFC 3986 form (correct scheme://host/path, percent-encode spaces and reserved chars).","If it is a local path, drop the URI-like prefix or pass it as a plain path so it takes the Paths.get branch.","Build the URI via URI.create/Paths.toUri() to catch encoding issues at the source.","Read the wrapped URISyntaxException cause for the exact error index and offending character."],"exampleFix":"// before\nuri = \"file://my dir/mod.pkl\" // URISyntaxException (space)\n// after\nuri = \"file:///my%20dir/mod.pkl\"","handlingStrategy":"validation","validationCode":"fun requireValidModuleUri(s: String) { if (s.contains(\"://\") || s.contains(\":\")) { try { URI(s) } catch (e: URISyntaxException) { throw InvalidUserDataException(\"Malformed module URI '$s': ${e.reason} at ${e.index}\", e) } } }","typeGuard":"fun isUriLikeAndValid(s: String): Boolean = !s.contains(\"://\") || try { URI(s); true } catch (e: URISyntaxException) { false }","tryCatchPattern":"try { parseModuleNotation(uriString) } catch (InvalidUserDataException e) { if (e.cause is URISyntaxException) logger.error(\"Malformed URI '$uriString': check scheme and encoding\"); throw e }","preventionTips":["Copy module URIs exactly from docs; watch for single vs double slashes","Build URIs programmatically (URI.create, Path.toUri) instead of by hand","Reject user input containing spaces/braces before it reaches plugin config","Add a config-validation step that parses all module URIs at startup"],"tags":["gradle","pkl","uri","parsing"],"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"}