zeroclaw-labs/zeroclaw · error · anyhow::Error

grok_cli requires an explicit working_directory for the ACP

Error message

grok_cli requires an explicit working_directory for the ACP session boundary

What it means

grok_cli is ACP-backed and refuses to construct without an explicit working_directory: it defines the filesystem boundary of the ACP session, so unlike other providers no default or cwd fallback is guessed. validate_working_directory rejects empty/whitespace values with this bail.

Source

Thrown at crates/zeroclaw-providers/src/grok_cli.rs:487

impl GrokCliModelProvider {
    /// Start a labelled construction chain for an ACP-backed provider.
    pub fn builder(alias: &str) -> GrokCliBuilder {
        GrokCliBuilder {
            alias: alias.to_string(),
            binary_path: None,
            working_directory: None,
            env_passthrough: Vec::new(),
            extra_args: Vec::new(),
            max_acp_stdout_bytes: None,
            timeout_secs: None,
            vision_enabled: false,
        }
    }

    fn validate_working_directory(value: &str) -> anyhow::Result<PathBuf> {
        let trimmed = value.trim();
        if trimmed.is_empty() {
            anyhow::bail!(
                "grok_cli requires an explicit working_directory for the ACP session boundary"
            );
        }
        let path = Path::new(trimmed);
        if !path.is_absolute() {
            anyhow::bail!("grok_cli working_directory must be an absolute path");
        }
        let canonical = std::fs::canonicalize(path).map_err(|_| {
            anyhow::Error::msg("grok_cli working_directory does not exist or is inaccessible")
        })?;
        if !canonical.is_dir() {
            anyhow::bail!("grok_cli working_directory must identify a directory");
        }
        Ok(canonical)
    }

    fn validate_acp_stdout_limit(value: Option<usize>) -> anyhow::Result<usize> {
        let limit = value.unwrap_or(acp::DEFAULT_ACP_STDOUT_LIMIT_BYTES);

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Set working_directory to an existing absolute directory (typically the project root) on the builder or in config
  2. Validate config presence at startup, not at first chat call

Example fix

// before
let provider = GrokCliModelProvider::builder("grok").build()?;

// after
let provider = GrokCliModelProvider::builder("grok")
    .working_directory("/home/user/project")
    .build()?;
Defensive patterns

Strategy: validation

Validate before calling

fn working_directory_specified(v: &str) -> bool {
    !v.trim().is_empty()
}

Type guard

fn working_directory_specified(v: &str) -> bool { !v.trim().is_empty() }

Try / catch

if let Err(e) = GrokCliModelProvider::builder("grok").build().check() {
    if e.to_string().contains("explicit working_directory") {
        return Err(anyhow::anyhow!("set grok_cli working_directory in config"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Building a GrokCliModelProvider without calling .working_directory(...) on the builder; a config entry whose working_directory is missing, empty, or whitespace.

Common situations: Config template copied without the field; assuming the daemon's cwd is used like other providers; YAML null coerced to empty string.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/f1cd3fe0a2e93e7e. Report an issue: GitHub.