xai-org/grok-build · error · anyhow::Error

e.error (daemon error message propagated via anyhow!)

Error message

e.error (daemon error message propagated via anyhow!)

What it means

Inside query_phase, when the daemon answers `Response::Err(e)`, the daemon's error string `e.error` is wrapped via `anyhow!` into an `NfsTryError::Other`. The resulting message is the daemon-side explanation (e.g. unknown worktree, declined, storage full), not a client-side message.

Source

Thrown at crates/codegen/xai-fast-worktree/src/nfs/client.rs:230

            v: PROTOCOL_VERSION,
            worktree_id: worktree_id.to_owned(),
        };
        match self.call(&req, self.ping_timeout.max(QUERY_PHASE_MIN_TIMEOUT)) {
            Ok(Response::Ok(body)) => Ok(QuerySnapshot {
                phase: body.create_phase,
                declined: body.declined,
                storage_full: body.storage_full,
                unknown: false,
                mount: body.mount,
            }),
            Ok(Response::Err(e)) if e.error.contains("unknown worktree_id") => Ok(QuerySnapshot {
                phase: None,
                declined: None,
                storage_full: false,
                unknown: true,
                mount: None,
            }),
            Ok(Response::Err(e)) => Err(NfsTryError::Other(anyhow!(e.error))),
            Err(e) => Err(NfsTryError::Other(e)),
        }
    }

    pub fn cancel_worktree_create(&self, worktree_id: &str) -> Result<(), anyhow::Error> {
        if !self.ping() {
            anyhow::bail!("grove daemon unreachable");
        }
        let req = Request::CancelWorktreeCreate {
            v: PROTOCOL_VERSION,
            worktree_id: worktree_id.to_owned(),
        };
        match self.call(&req, REMOVE_RPC_TIMEOUT) {
            Ok(Response::Ok(_)) => Ok(()),
            Ok(Response::Err(e)) => Err(anyhow!(e.error)),
            Err(e) => Err(e),
        }
    }

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Read the propagated daemon message to identify the specific cause (unknown/declined/storage_full/mount)
  2. Re-check the worktree_id used in the request matches one the daemon knows
  3. Check daemon availability and restart state; retry creation if state was lost
  4. Free NFS storage if the message indicates the export is full

Example fix

// handle daemon rejection explicitly
match client.query_phase(&id) {
    Ok(reply) => { /* use reply.phase */ }
    Err(NfsTryError::Other(e)) => eprintln!("daemon rejected: {e}"),
    Err(e) => eprintln!("transport error: {e}"),
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Prefer structured reply over string matching:
let reply = client.query_phase(&id)?;
if reply.unknown {
    // daemon does not know this id — recreate before proceeding
}
if reply.storage_full {
    // free space on the NFS export before retrying
}

Type guard

fn daemon_rejection(err: &NfsTryError) -> Option<String> {
    match err {
        NfsTryError::Other(e) => Some(e.to_string()),
        _ => None,
    }
}

Try / catch

match client.query_phase(&id) {
    Ok(r) => handle(r),
    Err(NfsTryError::Other(e)) => eprintln!("daemon error: {e}"),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling query_phase while the daemon rejects the request: worktree id unknown to the daemon, creation declined by policy, NFS storage full, or a mount error reported by the daemon.

Common situations: Polling after a lost reply for a create that never registered; daemon restarted losing in-memory worktree state; NFS export hitting capacity; version mismatch between client and daemon causing rejected requests.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/9d1db6c5d5c896bf. Report an issue: GitHub.