xai-org/grok-build · error
{LOCAL_WORKSPACE_ACK_REQUIRED}
Error message
{LOCAL_WORKSPACE_ACK_REQUIRED} What it means
Local workspace activation is gated by a human-in-the-loop acknowledgement. `emit_local_workspace_startup_ux_with` prints a banner, and if no prior ACK exists (GROK_CHAT_LOCAL_WORKSPACE_ACK truthy or ack file present) and stdin is not a terminal, it fails closed with `LOCAL_WORKSPACE_ACK_REQUIRED` (session_startup.rs:554) rather than proceeding without consent.
Source
Thrown at crates/codegen/xai-grok-pager/src/app/session_startup.rs:554
/// Testable UX gate: `stdin_is_terminal` is injected.
#[cfg(feature = "local-workspace")]
pub fn emit_local_workspace_startup_ux_with(
cfg: &LocalWorkspaceConfig,
stdin_is_terminal: bool,
) -> anyhow::Result<()> {
let cwd_display = cfg
.cwd
.as_ref()
.map(|p| p.display().to_string())
.unwrap_or_else(|| "<session cwd>".to_string());
let banner = LOCAL_WORKSPACE_BANNER.replace("<cwd>", &cwd_display);
eprintln!("{banner}");
eprintln!("{LOCAL_WORKSPACE_HITL_HINT}");
if local_workspace_ack_satisfied() {
return Ok(());
}
if !stdin_is_terminal {
anyhow::bail!("{LOCAL_WORKSPACE_ACK_REQUIRED}");
}
eprint!("Continue with local workspace on this machine? [y/N] ");
use std::io::Write;
let _ = std::io::stderr().flush();
let mut line = String::new();
std::io::stdin().read_line(&mut line)?;
let ok = matches!(line.trim(), "y" | "Y" | "yes" | "YES");
if !ok {
anyhow::bail!("local workspace cancelled");
}
write_local_workspace_ack();
Ok(())
}
/// True when ACK env or ack file already authorizes local workspace.
#[cfg(feature = "local-workspace")]
pub fn local_workspace_ack_satisfied() -> bool {
if env_truthy(GROK_CHAT_LOCAL_WORKSPACE_ACK_ENV) {
return true;View on GitHub (pinned to bc7f02eddd)
Solutions
- Set GROK_CHAT_LOCAL_WORKSPACE_ACK=1 in the environment for non-interactive runs
- Answer the interactive `Continue with local workspace? [y/N]` prompt once in a TTY so the ack file persists
- Run interactively in a terminal for the first activation
- Pre-create the ack file at the path `local_workspace_ack_path()` expects
Example fix
// before grok-pager --chat --local-workspace-own < input.txt // after GROK_CHAT_LOCAL_WORKSPACE_ACK=1 grok-pager --chat --local-workspace-own < input.txt
Defensive patterns
Strategy: fallback
Validate before calling
fn ack_ready() -> bool {
std::env::var("GROK_CHAT_LOCAL_WORKSPACE_ACK").ok().as_deref() == Some("1")
|| std::path::Path::new(&ack_file_path()).is_file()
} Try / catch
match run_with_local_workspace(args) {
Err(e) if e.to_string().contains("ACK") => {
eprintln!("non-interactive run: set GROK_CHAT_LOCAL_WORKSPACE_ACK=1 after reviewing the banner: {e}");
std::process::exit(2);
}
other => other?,
} Prevention
- Answer the interactive [y/N] prompt once in a TTY to persist the ack file
- Set GROK_CHAT_LOCAL_WORKSPACE_ACK=1 in CI/job environments that need local workspace
- Avoid detaching the TTY (nohup, systemd) before first activation
- Only set the ACK env after reviewing the local-workspace banner
When it happens
Trigger: Running the chat CLI with a local workspace enabled in non-interactive contexts: CI jobs, piped/redirected stdin, `nohup`, systemd services, docker exec without -t, when neither the ACK env var nor the ack file exists.
Common situations: First local-workspace run inside CI; scheduling the tool where stdin is /dev/null; running via a wrapper that detaches the TTY before the interactive confirm could be answered.
Related errors
- {LOCAL_WORKSPACE_REQUIRES_CHAT}
- invalid {GROK_CHAT_LOCAL_WORKSPACE_MODE_ENV}={other:?}; expe
- {LOCAL_WORKSPACE_ATTACH_NEEDS_SERVER_ID}
- local workspace cwd must exist and be canonicalizable: {}: {
- local workspace cwd must be an existing directory: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/e9401357a14d5b2e.
Report an issue: GitHub.