libnyanpasu/clash-nyanpasu · critical
invalid url
Error message
invalid url
What it means
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.
Source
Thrown at backend/boa_utils/src/module/http.rs:94
}
};
// Could also add a path if needed.
let source = Source::from_bytes(source_str.as_bytes());
Module::parse(source, None, context)
}
}
impl ModuleLoader for HttpModuleLoader {
async fn load_imported_module(
self: Rc<Self>,
_referrer: boa_engine::module::Referrer,
request: ModuleRequest,
context: &RefCell<&mut Context>,
) -> JsResult<Module> {
let url = request.specifier().to_std_string_escaped();
let url = Url::from_str(&url).expect("invalid url"); // SAFETY: `url` is a valid URL, if it's not, its caller side issue
let cache_path = self.mapping_cache_dir(&url);
let parent_dir = cache_path
.parent()
.ok_or_else(|| {
log::error!("failed to get parent directory for `{url}`");
JsNativeError::typ().with_message(format!(
"failed to get cache parent directory for `{url}`; path: `{}`",
cache_path.display()
))
})?
.to_path_buf();
let max_age = self.max_age;
log::debug!("checking cache for `{url}`...");
let now = SystemTime::now();
let should_use_cached_content = match async_fs::metadata(&cache_path).await {View on GitHub (pinned to f7dbce2997)
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.
Example fix
// before
let url = Url::from_str(&url).expect("invalid url");
// after
let url = Url::from_str(&url).map_err(|_| JsNativeError::typ().with_message(format!("invalid url: {url}")))?; Defensive patterns
Strategy: validation
Validate before calling
function assertAbsoluteUrl(specifier) {
const u = new URL(specifier);
if (!(u.protocol === 'https:' || u.protocol === 'http:')) {
throw new Error(`import specifier must be absolute http(s) URL: ${specifier}`);
}
return u.href;
}
// call before dynamic import: import(assertAbsoluteUrl(spec)) Type guard
function isAbsoluteHttpUrl(s) {
try { const u = new URL(s); return u.protocol === 'http:' || u.protocol === 'https:'; }
catch { return false; }
} Try / catch
try {
await import(spec);
} catch (e) {
// loader panics on non-URL specifiers; validate first, never pass relative paths
console.error('module load failed (use absolute URLs):', spec);
} Prevention
- 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
When it happens
Trigger: 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`.
Common situations: 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'`.
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
- should never drop oneshot tx
- Local socket too many crashes
- PAC script must contain FindProxyForURL function
- {:?}
- parse error: {}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/709cb5a863576fd4.
Report an issue: GitHub.