RightNow-AI/openfang · error
Invalid server URL
Error message
Invalid server URL
What it means
`run()` builds the URL string `http://127.0.0.1:{port}` and parses it into a Tauri `WebviewUrl::External(...)` which requires a `url::Url`. The `.expect("Invalid server URL")` panics if `str::parse::<Url>()` fails. With a well-formed literal and a valid port this should never fail in practice — it fires only if `port` produced a malformed URL (e.g. NaN/overflow through formatting) or the literal string is edited incorrectly.
Source
Thrown at crates/openfang-desktop/src/lib.rs:115
commands::get_agent_count,
commands::import_agent_toml,
commands::import_skill_file,
commands::get_autostart,
commands::set_autostart,
commands::check_for_updates,
commands::install_update,
commands::open_config_dir,
commands::open_logs_dir,
])
.setup(move |app| {
// Create the main window pointing directly at the embedded HTTP server.
// We do NOT define windows in tauri.conf.json because Tauri would try to
// load index.html from embedded assets (which don't exist), causing a race
// condition where AssetNotFound overwrites the navigated page.
let _window = WebviewWindowBuilder::new(
app,
"main",
WebviewUrl::External(url.parse().expect("Invalid server URL")),
)
.title("OpenFang")
.inner_size(1280.0, 800.0)
.min_inner_size(800.0, 600.0)
.center()
.visible(true)
.build()?;
// Set up system tray (desktop only)
#[cfg(desktop)]
tray::setup_tray(app)?;
// Spawn background task to forward critical kernel events as native
// OS notifications. Only truly critical events — crashes, hard quota
// limits, and kernel shutdown. Health checks and quota warnings are
// too noisy for desktop notifications.
let app_handle = app.handle().clone();
let mut event_rx = kernel_for_notifications.event_bus.subscribe_all();View on GitHub (pinned to acf2587e46)
Solutions
- Check how `port` is produced (crates/openfang-desktop/src/lib.rs:45) — ensure `start_server` returned a real bound port, not 0 or a default.
- Validate the formatted URL parses before handing it to Tauri and log the offending string.
- Use `Url::parse` with error propagation instead of `.expect` so a bad port yields a readable error.
Example fix
// before
WebviewUrl::External(url.parse().expect("Invalid server URL")),
// after
let parsed = url::Url::parse(&url)
.map_err(|e| anyhow!("Invalid server URL '{url}': {e}"))?;
WebviewUrl::External(parsed), Defensive patterns
Strategy: validation
Validate before calling
let url_str = format!("http://127.0.0.1:{port}");
let parsed: url::Url = url::Url::parse(&url_str)
.map_err(|e| anyhow!("bad server url '{url_str}': {e}"))?;
if parsed.port() != Some(port) {
return Err(anyhow!("port mismatch in url {url_str}"));
} Type guard
fn is_valid_http_url(s: &str) -> bool {
url::Url::parse(s).map(|u| u.scheme() == "http" || u.scheme() == "https").unwrap_or(false)
} Try / catch
// parse with error propagation, no expect
let external = url.parse().map_err(|e| anyhow!("Invalid server URL '{url}': {e}"))?; Prevention
- Never let port default to 0/unset before formatting the URL
- Always parse-and-check URLs before passing to WebviewUrl::External
- Log the exact URL string on failure for diagnosis
- Keep the URL literal centralized so refactors can't corrupt it
When it happens
Trigger: `port` value formatting into the URL is out of range or non-numeric, the base literal `http://127.0.0.1:{port}` is modified to an invalid scheme/host, or the port is left as 0/unset by a failed/short-circuited server startup path.
Common situations: After refactoring how the port is obtained (e.g. making `server_handle.port` optional or defaulting to 0), editing the URL format string with a typo, or constructing the URL from user/config-supplied host strings.
Related errors
- Failed to build Tauri application
- Failed to decode tray icon PNG
- Failed to start OpenFang server
- Failed to create tokio runtime for embedded server
AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02).
Data as JSON: /api/errors/bc70cb201edf84eb.
Report an issue: GitHub.