aaif-goose/goose · error · anyhow::Error

Requested mode(s) [{}] not offered by agent. Available modes

Error message

Requested mode(s) [{}] not offered by agent. Available modes: {}

What it means

When a session exposes modes, apply_session_mode computes candidate mode ids from the provider config plus the current goose mode, then calls select_mode_id to intersect them with the agent's advertised available_modes. If the intersection is empty, this error lists the requested candidates and the agent's actual available mode ids so the mismatch is visible.

Source

Thrown at crates/goose/src/acp/provider.rs:1463

async fn apply_session_mode(
    config: &AcpProviderConfig,
    goose_mode: &Arc<Mutex<GooseMode>>,
    cx: &ConnectionTo<Agent>,
    session: NewSessionResponse,
) -> Result<NewSessionResponse> {
    let current_mode = goose_mode.lock().ok().map(|mode| *mode);
    let candidates = initial_mode_candidates(config, current_mode);

    if let Some(modes) = session.modes.as_ref() {
        if !candidates.is_empty() {
            let Some(mode_id) = select_mode_id(&candidates, Some(modes)) else {
                let available: Vec<String> = modes
                    .available_modes
                    .iter()
                    .map(|mode| mode.id.0.to_string())
                    .collect();
                return Err(anyhow::anyhow!(
                    "Requested mode(s) [{}] not offered by agent. Available modes: {}",
                    candidates.join(", "),
                    available.join(", ")
                ));
            };
            if modes.current_mode_id.0.as_ref() != mode_id.as_str() {
                let _: SetSessionModeResponse = cx
                    .send_request(SetSessionModeRequest::new(
                        session.session_id.clone(),
                        mode_id,
                    ))
                    .block_task()
                    .await
                    .map_err(|err| {
                        anyhow::anyhow!(
                            "ACP agent rejected {}: {err}",
                            AGENT_METHOD_NAMES.session_set_mode
                        )

View on GitHub (pinned to 3810898a74)

Solutions

  1. Pick one of the ids from the 'Available modes' list in the error and use it as the requested mode
  2. Remove the mode override from the provider config so the default/current mode is used without a set_mode call
  3. If the agent should offer the mode, update/extend the agent to advertise it in its modes.available_modes

Example fix

# before
mode: approval            # not offered by this agent

# after
mode: primary             # taken from the error's Available modes list
Defensive patterns

Strategy: validation

Validate before calling

fn pick_mode<'a>(candidates: &[String], modes: &'a SessionModes) -> Option<&'a str> {
    modes
        .available_modes
        .iter()
        .map(|m| m.id.0.as_str())
        .find(|id| candidates.iter().any(|c| c == id))
}

assert!(pick_mode(&candidates, modes).is_some(), "mode not offered by agent");

Try / catch

match apply_session_mode(config, &mode, cx, session).await {
    Err(e) if e.to_string().contains("not offered by agent") => {
        tracing::warn!(%e, "falling back to agent default mode");
        Ok(session) // proceed with current_mode_id
    }
    r => r,
}

Prevention

When it happens

Trigger: The provider config requests a mode (e.g. 'approval') or the active goose mode maps to an id the agent does not offer — the agent only exposes ids like 'primary'/'edit', or a custom agent uses entirely different mode names.

Common situations: Setting a mode override in config for one agent and reusing that config with another agent; agents renaming modes between versions; a custom ACP agent with bespoke mode ids.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/0e9ca5eecb96e7e5. Report an issue: GitHub.