Hmbown/CodeWhale · error · anyhow::Error
Codewhale web is loopback-only and must bind to 127.0.0.1
Error message
Codewhale web is loopback-only and must bind to 127.0.0.1
What it means
For `codewhale serve --web`, the bind host produced by resolve_serve_bind_host(args.mobile, args.host) must be exactly the string 127.0.0.1. Web mode is loopback-only by design — it serves the web surface without the auth hardening required for wider exposure — so the check is a literal comparison and anything else (0.0.0.0, a LAN IP, even `localhost`) is rejected before the HTTP server starts.
Source
Thrown at crates/tui/src/lib.rs:2260
let workspace = cli.workspace.clone().unwrap_or_else(|| {
std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
});
let http_selected = validate_serve_mode_selection(
args.mcp,
args.http,
args.mobile,
args.web,
args.acp,
)?;
if args.mcp {
tokio::task::block_in_place(|| mcp_server::run_mcp_server(workspace))
} else if http_selected {
let (config, config_profile) =
load_config_from_cli_with_effective_profile(&cli)?;
let cors_origins = resolve_cors_origins(&config, &args.cors_origin);
let bind_host = resolve_serve_bind_host(args.mobile, args.host);
if args.web && bind_host.host != "127.0.0.1" {
bail!("Codewhale web is loopback-only and must bind to 127.0.0.1");
}
if bind_host.mobile_rebound_to_lan {
println!(
"WARNING: --mobile is binding to 0.0.0.0 so LAN devices can reach the mobile control page. Use --host 127.0.0.1 to keep mobile loopback-only."
);
}
runtime_api::run_http_server(
config,
workspace,
std::sync::Arc::clone(&plugin_discovery),
runtime_api::RuntimeApiOptions {
host: bind_host.host,
port: args.port,
workers: args.workers.clamp(1, 8),
cors_origins,
auth_token: args.auth_token,
insecure_no_auth: args.insecure_no_auth,
mobile: args.mobile,View on GitHub (pinned to 0c42157ee5)
Solutions
- Run `codewhale serve --web` with no --host (loopback default) or pass `--host 127.0.0.1` explicitly
- Reach a loopback web UI from another device via an SSH tunnel instead of widening the bind
- If LAN reachability is the actual requirement, use --mobile, which is built for that and prints its LAN warning
Example fix
# before codewhale serve --web --host 0.0.0.0 # after codewhale serve --web # loopback-only ssh -L 8080:127.0.0.1:8080 user@host # remote access via tunnel
Defensive patterns
Strategy: validation
Validate before calling
# Web mode must stay loopback; assert before launch
if $WEB && [ "${HOST:-127.0.0.1}" != '127.0.0.1' ]; then
echo '--web requires --host 127.0.0.1 (loopback-only)'; exit 2
fi Type guard
fn web_bind_allowed(web: bool, host: &str) -> bool {
!web || host == "127.0.0.1"
} Prevention
- Never template --host 0.0.0.0 into shared serve launchers
- Use --mobile when LAN reachability is the goal; keep --web loopback
- Use literal 127.0.0.1, not 'localhost', when overriding --host for --web
When it happens
Trigger: `codewhale serve --web --host 0.0.0.0`; `--web --host <lan-ip>` to share the UI; `--web --host localhost` (fails the literal comparison); docker/launcher presets that default --host to 0.0.0.0 for all modes.
Common situations: Trying to expose the web UI to a team or another machine; container port-forward setups; muscle memory from --mobile (which warns and rebinds to 0.0.0.0) applied to --web (which hard-fails).
Related errors
- --web is mutually exclusive with --http and --mobile
- Codewhale web is loopback-only and must bind to 127.0.0.1
- unit must be 'chars' or 'lines'
- max_chars must be > 0
- `codewhale account` does not accept the global `--api-key` f
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/b911bb488cb8aa90.
Report an issue: GitHub.