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

ACP agent rejected session/set_mode: {err}

Error message

ACP agent rejected session/set_mode: {err}

What it means

The intersection succeeded (a concrete mode_id was selected and differs from the session's current_mode_id), but the subsequent session/set_mode RPC was answered with an error by the agent. So the agent advertised the mode yet refused to activate it — a runtime rejection rather than a capability mismatch.

Source

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

                    .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
                        )
                    })?;
            }
        }
    }

    Ok(session)
}

fn initial_mode_candidates(
    config: &AcpProviderConfig,
    current_mode: Option<GooseMode>,
) -> Vec<String> {
    current_mode
        .and_then(|mode| config.mode_mapping.get(&mode).cloned())
        .or_else(|| config.session_mode_id.clone().map(|id| vec![id]))

View on GitHub (pinned to 3810898a74)

Solutions

  1. Retry creating the session — if it was a race with session teardown it will succeed
  2. Update the agent to a version where set_mode works for the advertised modes
  3. As a workaround, drop the mode override so no set_mode call is made, and select the mode inside the agent if it supports it

Example fix

# before: mode requested that agent advertises but rejects
mode: edit

# after: let the agent start in its default mode
# (remove the override; file an issue against the agent's set_mode handler)
Defensive patterns

Strategy: retry

Try / catch

let mut attempts = 0;
loop {
    match apply_session_mode(config, &mode, cx, session.clone()).await {
        Ok(s) => break Ok(s),
        Err(e) if e.to_string().contains("set_mode") && attempts < 2 => {
            attempts += 1;
            session = new_session(cx).await?; // rebuild then retry
        }
        Err(e) => break Err(e),
    }
}

Prevention

When it happens

Trigger: The mode id matches an advertised mode but the agent's internal state rejects the transition (session already closed, license/feature gate, or an agent-side validation bug); a race where the session ends between session/new and session/set_mode.

Common situations: Agent version bugs in mode handling, concurrent session/close racing the set_mode call, or an agent that lists modes it cannot actually switch to under the current configuration.

Related errors


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