Hmbown/CodeWhale · error
{message}
Error message
{message} What it means
This refusal is raised before spawning any process when the tool detects that the command would inherit the agent's own interactive terminal and take over its foreground TTY. On Unix, foreground process-group ownership cannot be transferred safely from the running TUI (cooked-mode Ctrl+C would terminate both parent and child), so the tool fails closed rather than spawning. The concrete message is produced by `inherited_interactive_terminal_refusal()` and explains the supported alternatives.
Solutions
- Run the command with `background: true, tty: true`, then continue it with `action: "interact"` and the returned `task_id`
- Use `terminal/run` and `terminal/send` for a persistent interactive PTY lane
- Launch the command in a new terminal window instead of the agent's terminal
- For non-interactive work, omit `interactive: true` entirely
Example fix
// before
{ "command": "htop", "interactive": true }
// after
{ "command": "htop", "tty": true, "background": true } Defensive patterns
Strategy: validation
Validate before calling
// Unix: interactive inheritance is never allowed, check the flag first
if request.interactive {
// route through background tty or terminal/run instead
} Prevention
- Never use interactive: true on Unix with the one-shot shell tool
- Remember the platform difference: the refusal exists on all Unix targets and is absent on non-Unix
- Use terminal/run + terminal/send or background tty for anything interactive
When it happens
Trigger: Calling the shell tool with `interactive: true` on Unix, so the child would inherit the operator's live terminal; the guard `inherited_interactive_terminal_refusal()` returns Some(message) for all Unix targets (with a variant text on ohos) and None only on non-Unix platforms.
Common situations: Agents attempt to run interactive/foreground terminal programs (vim, top, ssh with prompts) attached to the live terminal; porting or testing on Linux/macOS where interactive inheritance is never allowed; behavior differs across platforms since non-Unix builds skip this check.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Inherited interactive terminal takeover is unavailable on…
- TTY mode requires background execution (set background…
- TTY shell mode is not supported on HarmonyOS/OpenHarmony…
- agent profile may not request allow_shell=true
- allowlisted read-only executable
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/079707ca3ca10ac3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/shell.rs:2233
pub fn execute_interactive_with_policy_env(
&mut self,
command: &str,
working_dir: Option<&str>,
timeout_ms: u64,
policy_override: Option<ExecutionSandboxPolicy>,
extra_env: HashMap<String, String>,
) -> Result<ShellResult> {
crate::shell_dispatcher::ShellDispatcher::log_exec(command);
// A new Unix process group that inherits the terminal is not its
// foreground owner. Letting it read stdin triggers SIGTTIN; sharing
// Codewhale's group instead would make cooked-mode Ctrl+C terminate
// both parent and child. Until this path owns a complete POSIX job-
// control lease, fail closed before spawning. Persistent PTY tools
// already provide a safe interactive lane without taking over the
// operator's live terminal.
if let Some(message) = inherited_interactive_terminal_refusal() {
return Err(anyhow!(message));
}
let work_dir = working_dir.map_or_else(|| self.default_workspace.clone(), PathBuf::from);
validate_shell_working_dir(&work_dir, working_dir.is_none())?;
let timeout_ms = timeout_ms.clamp(1000, 600_000);
let policy = policy_override.unwrap_or_else(|| self.sandbox_policy.clone());
let spec = CommandSpec::shell(command, work_dir.clone(), Duration::from_millis(timeout_ms))
.with_policy(policy)
.with_env(extra_env);
let exec_env = self.sandbox_manager.prepare(&spec);
Self::execute_interactive_sandboxed(command, &work_dir, timeout_ms, &exec_env)
}
/// Execute command synchronously with timeout (sandboxed).
fn execute_sync_sandboxed(View on GitHub (pinned to 73e0f67d83)