{"record":{"id":"f13f84be358de3e6","repo":"astrid-runtime/astrid","slug":"gateway-idle-shutdown-secs-must-be-positive-and-re","errorCode":null,"errorMessage":"gateway.idle_shutdown_secs must be positive and representable","messagePattern":"gateway\\.idle_shutdown_secs must be positive and representable","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/gateway.rs","lineNumber":478,"sourceCode":"        boot_token: boot_token.clone(),\n        armed: true,\n    };\n\n    // The gateway's authenticated uplinks keep an automatically started daemon\n    // alive. Releasing them after the final host disconnects lets it retire.\n    // An existing operator-started daemon retains its chosen lifetime.\n    crate::commands::daemon::ensure_daemon(\"mcp-gateway\")\n        .await\n        .context(\"failed to ensure Astrid daemon for MCP gateway\")?;\n\n    let idle_grace = Duration::from_secs(\n        astrid_config::Config::load(Some(&daemon_root))?\n            .config\n            .gateway\n            .idle_shutdown_secs,\n    );\n    if idle_grace.is_zero() || Instant::now().checked_add(idle_grace).is_none() {\n        anyhow::bail!(\"gateway.idle_shutdown_secs must be positive and representable\");\n    }\n\n    let hook_token = mint_hook_token();\n    let state = Arc::new(GatewayState::new(\n        daemon_root,\n        caller.clone(),\n        hook_token.clone(),\n    ));\n    // Warm the authenticated principal selected by `ready`/`gateway` before\n    // accepting any attach registration. The lease was published first so this\n    // slow, pre-listener generation remains authenticated-stop capable.\n    state.client_for(&caller).await?;\n    let socket_path = prepare_gateway_socket(&lifecycle).await?;\n    let listener = UnixListener::bind(&socket_path)\n        .with_context(|| format!(\"failed to bind MCP gateway at {}\", socket_path.display()))?;\n    set_socket_mode(&socket_path)?;\n    let ready = GatewayReady {\n        version: 1,","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/gateway.rs#L460-L496","documentation":"run() validates the configured gateway.idle_shutdown_secs before starting the gateway. The value must be strictly positive (zero disables the idle-shutdown grace in an invalid way here) and must fit into an Instant offset (checked_add must not overflow). Otherwise the gateway refuses to start with this bail.","triggerScenarios":"Setting gateway.idle_shutdown_secs to 0, to a negative value, or to a magnitude so large that Instant::now() + idle_grace overflows when loading astrid_config::Config in `run`.","commonSituations":"Typo or misunderstanding in the config file (e.g. idle_shutdown_secs: 0 thinking it means 'never idle-shutdown'); hand-editing the config with an absurdly large number of seconds; generating the config programmatically with an out-of-range integer.","solutions":["Set gateway.idle_shutdown_secs in your astrid config to a positive value (e.g. 30 or 60).","Do not use 0 to disable idle shutdown; use the config mechanism intended for disabling it, or a large-but-representable duration.","Clamp the configured value in code/config to a sane range such as 1..=86400 before launching the gateway.","Reload/re-verify the config after edits: astrid_config::Config::load(Some(&daemon_root)) picks up the file at daemon_root."],"exampleFix":"// before (config)\n[gateway]\nidle_shutdown_secs = 0\n// after\n[gateway]\nidle_shutdown_secs = 60","handlingStrategy":"validation","validationCode":"fn valid_idle_secs(v: i64) -> bool { v > 0 && v <= 86_400 }","typeGuard":"fn as_positive_secs(raw: &str) -> Option<u64> {\n    raw.trim().parse::<u64>().ok().filter(|&s| s > 0)\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"idle_shutdown_secs\") => eprintln!(\"fix [gateway].idle_shutdown_secs in your astrid config: must be > 0\"),\n    other => other?,\n}","preventionTips":["Never set idle_shutdown_secs to 0 expecting 'disabled'.","Clamp config values to 1..=86400 in tooling that generates the config.","Validate the config file after hand edits before launching the gateway.","Keep durations in one unit (seconds) to avoid magnitude mistakes."],"tags":["config","validation","gateway","duration"],"backgroundTag":"invalid-config-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}