zed-industries/zed · warning · anyhow::Error

{reason}

Error message

{reason}

What it means

The tool call was denied automatically by permission rules rather than by a human: during the settings race, `check_settings` returned `ToolPermissionDecision::Deny(reason)`. The agent resolves the tool call with the deny outcome and fails it with the rule's own reason string, so the message content comes from settings evaluation, not this code.

Source

Thrown at crates/agent/src/thread.rs:6502

                        // status with an internal selected outcome. Dropping
                        // `response_rx` prevents the synthetic response from
                        // being delivered back into this loop.
                        match cx.update(|cx| check_settings(cx)) {
                            ToolPermissionDecision::Allow => {
                                drop(response_rx);
                                stream.resolve_tool_call_authorization(
                                    &tool_call_id,
                                    auto_allow_outcome.clone(),
                                );
                                return Ok(());
                            }
                            ToolPermissionDecision::Deny(reason) => {
                                drop(response_rx);
                                stream.resolve_tool_call_authorization(
                                    &tool_call_id,
                                    auto_deny_outcome.clone(),
                                );
                                return Err(anyhow!(reason));
                            }
                            ToolPermissionDecision::Confirm => continue,
                        }
                    }
                }
            }
        })
    }

    /// Interprets a `SelectedPermissionOutcome` and persists any settings changes.
    /// Returns `true` if the tool call should be allowed, `false` if denied.
    fn persist_permission_outcome(
        outcome: &acp_thread::SelectedPermissionOutcome,
        fs: Option<Arc<dyn Fs>>,
        cx: &AsyncApp,
    ) -> Result<()> {
        let option_id = outcome.option_id.0.as_ref();
        let err = || Err(anyhow!("Permission to run tool denied by user"));

View on GitHub (pinned to bc538def45)

Solutions

  1. Read the reason string — it identifies the rule that denied the call; adjust or remove that rule in settings if the call is legitimate.
  2. Narrow overly-broad deny patterns or switch the tool back to 'ask' mode.
  3. Do not retry the identical call; change the approach or ask the user to update permissions.
Defensive patterns

Strategy: try-catch

Try / catch

match run_tool().await {
    Err(err) if err.to_string() == deny_reason_from_settings => {
        // Rule-driven denial: show the reason, do not retry the same call.
        report_denied_to_user(err.to_string());
        Ok(Default::default())
    }
    result => result,
}

Prevention

When it happens

Trigger: A deny rule matches the tool call — the user previously chose 'always deny' for this tool or command pattern, or a ruleset in settings denies it — and the evaluation fires either at prompt time or after a settings change re-triggers the check.

Common situations: An earlier 'Always deny' selection matching a broader pattern than intended; organization-wide settings with deny rules; the model retrying a tool that rules now block.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/8e168fd03ce88af2. Report an issue: GitHub.