{"record":{"id":"709cb5a863576fd4","repo":"libnyanpasu/clash-nyanpasu","slug":"invalid-url","errorCode":null,"errorMessage":"invalid url","messagePattern":"invalid url","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"backend/boa_utils/src/module/http.rs","lineNumber":94,"sourceCode":"            }\n        };\n\n        // Could also add a path if needed.\n        let source = Source::from_bytes(source_str.as_bytes());\n\n        Module::parse(source, None, context)\n    }\n}\n\nimpl ModuleLoader for HttpModuleLoader {\n    async fn load_imported_module(\n        self: Rc<Self>,\n        _referrer: boa_engine::module::Referrer,\n        request: ModuleRequest,\n        context: &RefCell<&mut Context>,\n    ) -> JsResult<Module> {\n        let url = request.specifier().to_std_string_escaped();\n        let url = Url::from_str(&url).expect(\"invalid url\"); // SAFETY: `url` is a valid URL, if it's not, its caller side issue\n        let cache_path = self.mapping_cache_dir(&url);\n        let parent_dir = cache_path\n            .parent()\n            .ok_or_else(|| {\n                log::error!(\"failed to get parent directory for `{url}`\");\n                JsNativeError::typ().with_message(format!(\n                    \"failed to get cache parent directory for `{url}`; path: `{}`\",\n                    cache_path.display()\n                ))\n            })?\n            .to_path_buf();\n\n        let max_age = self.max_age;\n\n        log::debug!(\"checking cache for `{url}`...\");\n\n        let now = SystemTime::now();\n        let should_use_cached_content = match async_fs::metadata(&cache_path).await {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/boa_utils/src/module/http.rs#L76-L112","documentation":"In the Boa JS runtime's HTTP module loader, `load_imported_module` parses the import specifier with `Url::from_str(...).expect(\"invalid url\")`. Because `.expect` panics rather than returning a JsResult, an import specifier that is not an absolute, valid URL aborts the thread with this message.","triggerScenarios":"A JS module executes `import ... from \"./relative/path\"` or any bare/non-URL specifier; `Url::from_str` fails and the expect panics inside `load_imported_module`.","commonSituations":"Scripts using relative imports (the loader only supports absolute http(s) URLs), typos in specifiers, or bundler-style bare imports like `import x from 'lodash'`.","solutions":["Use fully-qualified absolute URLs in import statements (e.g. `https://example.com/mod.js`).","Change the loader to return a JsNativeError instead of `.expect` to convert the panic into a catchable JS error.","Pre-register local modules in the module map so imports resolve without URL fetching."],"exampleFix":"// before\nlet url = Url::from_str(&url).expect(\"invalid url\");\n// after\nlet url = Url::from_str(&url).map_err(|_| JsNativeError::typ().with_message(format!(\"invalid url: {url}\")))?;","handlingStrategy":"validation","validationCode":"function assertAbsoluteUrl(specifier) {\n  const u = new URL(specifier);\n  if (!(u.protocol === 'https:' || u.protocol === 'http:')) {\n    throw new Error(`import specifier must be absolute http(s) URL: ${specifier}`);\n  }\n  return u.href;\n}\n// call before dynamic import: import(assertAbsoluteUrl(spec))","typeGuard":"function isAbsoluteHttpUrl(s) {\n  try { const u = new URL(s); return u.protocol === 'http:' || u.protocol === 'https:'; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  await import(spec);\n} catch (e) {\n  // loader panics on non-URL specifiers; validate first, never pass relative paths\n  console.error('module load failed (use absolute URLs):', spec);\n}","preventionTips":["Only use absolute http(s) URLs in imports under the Boa runtime","Never use relative or bare (package-name) specifiers with this loader","Prefer fixing the loader to return JsNativeError instead of .expect"],"tags":["javascript","boa","module-loader","url","panic"],"backgroundTag":"invalid-url-format","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}