gleam-lang/gleam · error

Error setting Ctrl-C handler

Error message

Error setting Ctrl-C handler

What it means

'gleam run' installs a no-op SIGINT handler with ctrlc::set_handler(...).expect("Error setting Ctrl-C handler") so Ctrl+C is forwarded to the child Erlang shell instead of killing gleam. The ctrlc crate allows only one handler per process, so set_handler returns an error if a handler is already installed, or when the signal machinery itself cannot be registered (e.g. seccomp blocking sigaction). The expect converts that into an immediate panic before the program starts.

Solutions

  1. Run 'gleam run' as its own process rather than embedded in a host that already owns the Ctrl+C handler
  2. Disable or remove the wrapper's own SIGINT handler before invoking gleam
  3. Relax the sandbox/seccomp profile so signal-handler registration succeeds
  4. Report to gleam if it panics in a normal standalone invocation
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: Embedding or wrapping 'gleam run' in a host process that already called ctrlc::set_handler (test harnesses, task runners), or running under a sandbox whose syscall filter blocks signal-handler registration.

Common situations: Custom tooling that embeds the gleam CLI in-process; wrappers that install their own Ctrl+C handling; hardened containers with seccomp profiles denying sigaction.

Related errors


AI-assisted analysis of gleam-lang/gleam@3e3c5ddc08 (2026-08-20). Data as JSON: /api/errors/3d65c16aed00b6dc. Report an issue: GitHub.

Appendix: source

Thrown at compiler-cli/src/run.rs:39

#[derive(Debug, Clone, Copy)]
pub enum Which {
    Src,
    Test,
    Dev,
}

pub fn command(
    paths: &ProjectPaths,
    arguments: Vec<String>,
    target: Option<Target>,
    runtime: Option<Runtime>,
    module: Option<String>,
    which: Which,
    no_print_progress: bool,
) -> Result<(), Error> {
    // Don't exit on ctrl+c as it is used by child erlang shell
    ctrlc::set_handler(move || {}).expect("Error setting Ctrl-C handler");
    let command = setup(
        paths,
        arguments,
        target,
        runtime,
        module,
        which,
        no_print_progress,
    )?;
    let status = ProjectIO::new().exec(command)?;
    std::process::exit(status);
}

pub fn setup(
    paths: &ProjectPaths,
    arguments: Vec<String>,
    target: Option<Target>,
    runtime: Option<Runtime>,

View on GitHub (pinned to 3e3c5ddc08)