BloopAI/vibe-kanban · error
Unexpected base URL scheme: {base_url}
Error message
Unexpected base URL scheme: {base_url} What it means
start_relay builds a WebSocket URL for the relay connection by rewriting the remote server's base URL scheme: https:// becomes wss:// and http:// becomes ws://. If the configured base URL uses any other (or no) scheme, the function bails with this message because it cannot derive a valid WebSocket endpoint. It is a configuration-validation guard against malformed REMOTE_BASE_URL-style inputs.
Source
Thrown at crates/server/src/runtime/relay_registration.rs:140
/// Start the relay client transport.
async fn start_relay(
params: &RelayParams,
shutdown: tokio_util::sync::CancellationToken,
) -> anyhow::Result<()> {
let base_url = params.relay_base.trim_end_matches('/');
let encoded_name = url::form_urlencoded::Serializer::new(String::new())
.append_pair("machine_id", ¶ms.machine_id)
.append_pair("name", ¶ms.host_nickname)
.append_pair("agent_version", env!("CARGO_PKG_VERSION"))
.finish();
let ws_url = if let Some(rest) = base_url.strip_prefix("https://") {
format!("wss://{rest}/v1/relay/connect?{encoded_name}")
} else if let Some(rest) = base_url.strip_prefix("http://") {
format!("ws://{rest}/v1/relay/connect?{encoded_name}")
} else {
anyhow::bail!("Unexpected base URL scheme: {base_url}");
};
let access_token = params
.remote_client
.access_token()
.await
.context("Failed to get access token for relay")?;
tracing::debug!(%ws_url, "Connecting relay control channel");
start_relay_client(RelayClientConfig {
ws_url,
bearer_token: access_token,
local_addr: params.server_addr,
shutdown,
})
.await
}View on GitHub (pinned to 4deb7eca8f)
Solutions
- Prefix the base URL with 'https://' (or 'http://' for local dev) before passing it to spawn_relay/start_relay.
- Normalize the value at config load: if it has no scheme, default to https://.
- Strip any user-supplied ws:// or wss:// scheme and store only the http(s) origin, letting start_relay do the conversion.
- Log/echo the offending base_url value from the error message and fix the environment variable or config file that supplies it.
Example fix
// before
let base_url = "myserver.example.com";
spawn_relay(base_url, ...).await?;
// after
let base_url = if base_url.starts_with("http") { base_url } else { format!("https://{base_url}") };
spawn_relay(&base_url, ...).await?; Defensive patterns
Strategy: validation
Validate before calling
fn ensure_http_base_url(base_url: &str) -> Result<(), String> {
if base_url.starts_with("https://") || base_url.starts_with("http://") {
Ok(())
} else {
Err(format!("base URL must start with http:// or https://, got: {base_url}"))
}
} Type guard
fn is_http_base_url(base_url: &str) -> bool {
base_url.starts_with("https://") || base_url.starts_with("http://")
} Try / catch
match start_relay(&base_url, params).await {
Ok(()) => {},
Err(e) if e.to_string().starts_with("Unexpected base URL scheme") => {
eprintln!("Fix base URL (must be http/https): {base_url}");
}
Err(e) => return Err(e),
} Prevention
- Always store the remote base URL with an explicit http(s) scheme in env/config.
- Normalize user input at config load time by prepending https:// when no scheme is present.
- Reject ws:// or wss:// values early — the relay derives the scheme itself.
- Add a startup config check that validates the base URL before any relay operations.
When it happens
Trigger: Calling spawn_relay (which calls start_relay) with a base_url that does not start with 'https://' or 'http://' — e.g. 'myserver.example.com', 'ftp://host', 'wss://host' already supplied, or an empty string.
Common situations: Developers set the remote base URL env var without a scheme, copy a host from docs without 'https://', or pre-convert to wss:// themselves and pass it in, not realizing the relay adds the scheme.
Related errors
- This host is not paired with your browser. Pair it in Relay
- No setup script configured for this project
- No cleanup script configured for this project
- No archive script configured for this project
- Raw stream should only have Stdout/Stderr/Finished
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/7ba03327c7dfab11.
Report an issue: GitHub.