clockworklabs/SpacetimeDB · error
failed to install Ctrl+C handler
Error message
failed to install Ctrl+C handler
What it means
The standalone `start` command installs a graceful-shutdown hook with `tokio::signal::ctrl_c().await.expect("failed to install Ctrl+C handler")` in the branch where the PostgreSQL wire-protocol server is disabled. Installation fails when the runtime/environment cannot register a SIGINT handler — restricted sandboxes (seccomp blocking signal syscalls), unusual init systems, or signal-capacity exhaustion.
Source
Thrown at crates/standalone/src/subcommands/start.rs:288
))?;
let notify = Arc::new(tokio::sync::Notify::new());
let shutdown_notify = notify.clone();
tokio::select! {
_ = pg_server::start_pg(notify.clone(), ctx, tcp_pg) => {},
_ = axum::serve(tcp, service).with_graceful_shutdown(async move {
shutdown_notify.notified().await;
}) => {},
_ = tokio::signal::ctrl_c() => {
println!("Shutting down servers...");
notify.notify_waiters(); // Notify all tasks
}
}
} else {
log::warn!("PostgreSQL wire protocol server disabled");
axum::serve(tcp, service)
.with_graceful_shutdown(async {
tokio::signal::ctrl_c().await.expect("failed to install Ctrl+C handler");
log::info!("Shutting down server...");
})
.await?;
}
Ok(())
}
/// Check if a port is available on the requested host for both IPv4 and IPv6.
///
/// On macOS (and some other systems), `localhost` can resolve to both IPv4 (127.0.0.1)
/// and IPv6 (::1). If SpacetimeDB binds only to IPv4 but another service is using the
/// same port on IPv6, browsers may connect to the wrong service depending on which
/// address they try first.
///
/// This function checks both the requested IPv4 address and its IPv6 equivalent:
/// - 127.0.0.1 -> also checks ::1
/// - 0.0.0.0 -> also checks ::View on GitHub (pinned to 524b4487d9)
Solutions
- Run the binary in a signal-capable environment (default Docker profile, systemd, a normal terminal), or loosen the sandbox profile to allow signal syscalls.
- Prefer driving shutdown through the documented graceful-shutdown path rather than relying on Ctrl+C in headless deployments.
- Reproduce under `docker run` defaults to confirm the sandbox is the cause.
Example fix
# before: hardened profile blocks signal setup and the server panics docker run --security-opt seccomp=no-signals.json spacetimedb start --no-pg # after: default profile permits sigaction, ctrl_c() installs cleanly docker run spacetimedb start --no-pg
Defensive patterns
Strategy: fallback
Prevention
- Use default container seccomp profiles; don't strip signal-related syscalls (sigaction/signal).
- Prefer supervisor-driven shutdown (SIGTERM via your init) over relying on Ctrl+C in dockerized servers.
- When sandboxing is required, keep the pg wire server branch enabled or use the documented shutdown path.
When it happens
Trigger: Running `spacetimedb start` with the pg wire server disabled inside a hardened container (seccomp/AppArmor profile denying sigaction), gVisor/Kata-style sandboxes, or process supervisors that block signal registration.
Common situations: Docker with a custom restrictive seccomp profile; sandboxed CI runners; multiple signal-hungry runtimes sharing one container.
Related errors
- never types are not yet supported in C# output
- No such saved server configuration: {server} Add a new serve
- No default server configuration. Set an existing server as t
- Server nickname {} already in use: {}://{}
- Server host name is ambiguous with existing server nickname:
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/36d741220736a804.
Report an issue: GitHub.