{"record":{"id":"4e631815b5e2d0fe","repo":"zeroclaw-labs/zeroclaw","slug":"cli-secret-needs-tty","errorCode":"cli-secret-needs-tty","errorMessage":"Secret input requires a terminal on stdin and stderr.","messagePattern":"Secret input requires a terminal on stdin and stderr\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/main.rs","lineNumber":151,"sourceCode":"    {\n        zeroclaw_runtime::i18n::get_required_cli_string_with_args(key, args)\n    }\n    #[cfg(not(feature = \"agent-runtime\"))]\n    {\n        fallback.to_string() // i18n-exempt: English fallback when Fluent (agent-runtime) is disabled\n    }\n}\n\n/// Interactive secret prompt with pre-submit feedback.\n///\n/// The value stays hidden, but the prompt shows a bounded mask once the input\n/// buffer becomes non-empty.\n#[cfg(feature = \"agent-runtime\")]\nfn secret_prompt(prompt_text: &str, allow_empty: bool) -> Result<String> {\n    use std::io::IsTerminal;\n\n    if !std::io::stdin().is_terminal() || !std::io::stderr().is_terminal() {\n        bail!(ta(\n            \"cli-secret-needs-tty\",\n            &[],\n            \"Secret input requires a terminal on stdin and stderr.\"\n        ));\n    }\n\n    let value = cli_input::SecretInput::new()\n        .with_prompt(prompt_text)\n        .interact()?;\n    if allow_empty || !value.trim().is_empty() {\n        Ok(value)\n    } else {\n        bail!(ta(\"cli-secret-empty\", &[], \"Value cannot be empty.\"))\n    }\n}\n\n#[cfg(feature = \"agent-runtime\")]\nfn qta(key: &str, args: &[(&str, &str)]) -> String {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/src/main.rs#L133-L169","documentation":"secret_prompt reads hidden input via cli_input::SecretInput, which needs a real terminal on both stdin (to read the secret) and stderr (to render the prompt and mask feedback). If either stream is not a TTY, the prompt cannot work safely and the call aborts before reading anything (i18n key 'cli-secret-needs-tty', stable code of the same name).","triggerScenarios":"Invoking any zeroclaw flow that prompts for a secret (e.g. provider API key onboarding) with stdin or stderr redirected: piping answers in (`echo y | zeroclaw ...`), running under CI, daemons, plain `docker exec` without -t, or scripts with stdin from a file.","commonSituations":"Automating first-run setup in containers or CI where no terminal exists; SSH one-shot commands (`ssh host zeroclaw ...` allocates no TTY); cron-invoked maintenance commands that hit an interactive path.","solutions":["Run the command from an interactive terminal so both stdin and stderr are TTYs.","In containers use `docker exec -it <container> zeroclaw ...`; over SSH drop one-shot mode so a TTY is allocated.","For automation, provision the secret non-interactively (config file or the documented env-var route) instead of relying on the prompt.","If you must automate the prompt, drive it through a pty wrapper such as `expect` or `script`."],"exampleFix":"# before: no tty, prompt aborts\ndocker exec zeroclaw zeroclaw onboard   # Secret input requires a terminal...\n# after: allocate a tty\ndocker exec -it zeroclaw zeroclaw onboard","handlingStrategy":"fallback","validationCode":"use std::io::IsTerminal;\nfn can_prompt_secret() -> bool {\n    std::io::stdin().is_terminal() && std::io::stderr().is_terminal()\n}\n// in automation: if !can_prompt_secret(), provision the secret via the\n// documented non-interactive route (config/env) instead of invoking the prompt","typeGuard":null,"tryCatchPattern":"match run_onboarding().await {\n    Err(e) if e.to_string().contains(\"requires a terminal\") => {\n        // no TTY: switch to the non-interactive provisioning path or re-run\n        // inside `docker exec -it` / an interactive ssh session\n    }\n    other => other,\n}","preventionTips":["Never pipe answers into zeroclaw commands that prompt for secrets; detect TTY first and branch.","Use `docker exec -it` for container onboarding and interactive ssh (no one-shot command) remotely.","Pre-provision secrets via config or env in CI so interactive prompts are never reached."],"tags":["cli","tty","stdin","automation","secret-input"],"backgroundTag":"stdin-not-a-tty","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}