{"record":{"id":"af86319dab6db2a5","repo":"jdx/mise","slug":"took-longer-than-s","errorCode":null,"errorMessage":"took longer than {}s","messagePattern":"took longer than (.+?)s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/describe_command.rs","lineNumber":167,"sourceCode":"    let stdout = child.stdout.take().expect(\"piped\");\n    let (sender, receiver) = std::sync::mpsc::channel();\n    std::thread::spawn(move || {\n        let mut out = Vec::new();\n        let _ = stdout.take(DIFF_LIMIT as u64 + 1).read_to_end(&mut out);\n        let _ = sender.send(out);\n    });\n    let started = Instant::now();\n    let status = loop {\n        if let Some(status) = child.try_wait()? {\n            break status;\n        }\n        if started.elapsed() >= timeout {\n            // the shell and whatever it started; the reader thread ends\n            // with the last writer of the pipe, so it is not waited for\n            active.0.kill();\n            let _ = child.kill();\n            let _ = child.wait();\n            bail!(\"took longer than {}s\", timeout.as_secs());\n        }\n        std::thread::sleep(Duration::from_millis(100));\n    };\n    // a descendant that outlived the shell and kept the pipe is not the\n    // shell's answer: the output is waited for a moment, not forever\n    let Ok(output) = receiver.recv_timeout(output_grace) else {\n        active.0.kill();\n        bail!(\"a process it started kept its output open\");\n    };\n    if output.len() > DIFF_LIMIT {\n        bail!(\"description output exceeded {} bytes\", DIFF_LIMIT);\n    }\n    if !status.success() {\n        bail!(\"exited with {status}\");\n    }\n    let Some(line) = first_line(&output) else {\n        return Ok(None);\n    };","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/describe_command.rs#L149-L185","documentation":"`run_with_limits` runs a command inside a shell with a hard timeout. If the command hasn't finished when `elapsed >= timeout`, mise kills the shell and child, then bails with `took longer than {N}s`. A descendant that outlived the shell is additionally given only a bounded output grace rather than waiting forever.","triggerScenarios":"The command passed to the describe/run-with-limits helper runs longer than the configured timeout (in seconds); the poll loop notices the deadline, kills the process group, and returns this error.","commonSituations":"A describe-command in config invokes a slow script (network calls, package installs) that exceeds the default timeout; a hung child keeps the pipe open causing follow-up output-grace behavior.","solutions":["Increase the configured timeout for this command in your history/describe configuration.","Make the command faster or asynchronous (cache results, skip network calls).","Fix the underlying hang (e.g. a prompt or daemon child that keeps the pipe open).","Set the timeout via the relevant env/config knob (e.g. MISE_HISTORY_* timeout settings) if available."],"exampleFix":"# before: describe command that times out\n[history.describe]\ncommand = \"curl -s https://slow-api.example.com/status\"\n# after: bound it and raise the timeout\ntimeout = 30\n[history.describe]\ncommand = \"curl -s --max-time 10 https://slow-api.example.com/status\"","handlingStrategy":"retry","validationCode":"start=$(date +%s); your_slow_command; end=$(date +%s); [ $((end-start)) -lt 30 ] || echo 'will exceed timeout, raise it'","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"took longer than\") => retry_with_longer_timeout(cmd),\n    other => other?,\n}","preventionTips":["Size the timeout to the slowest legitimate command","Avoid network calls in describe commands or cache their results","Investigate hung descendants that keep pipes open","Raise the timeout in history/describe config for known-slow commands"],"tags":["timeout","command","history"],"backgroundTag":"request-timeout","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}