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
- Pick one of the ids from the 'Available modes' list in the error and use it as the requested mode
- Remove the mode override from the provider config so the default/current mode is used without a set_mode call
- 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
- Read available_modes from the session response before configuring a mode
- Do not copy mode settings between different agents
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
- ACP agent rejected session/set_config_option for '{}': {err}
- ACP agent does not support session/load
- ACP agent rejected session/set_mode: {err}
- {e}
- Provider rejected mode update: {e}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/0e9ca5eecb96e7e5.
Report an issue: GitHub.