BigPizzaV3/CodexPlusPlus · error

模型路由目标不能是聚合供应商:{}

Error message

模型路由目标不能是聚合供应商:{}

What it means

Thrown by select_model_route in crates/codex-plus-core/src/protocol_proxy.rs when a model route's target relay resolves to a profile whose relay_mode is RelayMode::Aggregate. The model-route mechanism forwards a single request directly to the target provider; an aggregate target would need its own member rotation and is not supported, so the proxy refuses. The placeholder is the target aggregate's display name.

Source

Thrown at crates/codex-plus-core/src/protocol_proxy.rs:743

    let Some(route) = source
        .model_routes
        .iter()
        .find(|route| route.model.trim() == model)
    else {
        return Ok(None);
    };
    let target_relay_id = route.target_relay_id.trim();
    if target_relay_id == source.id {
        anyhow::bail!("模型路由不能指向当前供应商自身:{model}");
    }
    let target = settings
        .relay_profiles
        .iter()
        .find(|profile| profile.id == target_relay_id)
        .cloned()
        .with_context(|| format!("模型路由目标供应商不存在:{target_relay_id}"))?;
    if target.relay_mode == crate::settings::RelayMode::Aggregate {
        anyhow::bail!("模型路由目标不能是聚合供应商:{}", target.name);
    }
    if target.protocol != RelayProtocol::Responses {
        anyhow::bail!("模型路由目标必须使用 Responses API:{}", target.name);
    }

    let upstream_model = if route.target_model.trim().is_empty() {
        model.to_string()
    } else {
        route.target_model.trim().to_string()
    };
    Ok(Some(ModelRouteSelection {
        relay: target,
        source_relay_id: source.id,
        source_model: model.to_string(),
        upstream_model,
    }))
}

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Edit the failing model route and set target_relay_id to a concrete (non-aggregate) provider profile
  2. If you want load balancing for that model, instead make the aggregate the active provider and let its rotation handle members
  3. If routing through a pool is required, route to one specific member relay of the pool rather than the aggregate itself
Defensive patterns

Strategy: validation

Validate before calling

fn route_target_is_concrete(settings: &BackendSettings, target_id: &str) -> bool {
    settings
        .relay_profiles
        .iter()
        .any(|p| p.id == target_id && p.relay_mode != RelayMode::Aggregate)
}

Prevention

When it happens

Trigger: A model_routes entry whose target_relay_id points at an aggregate provider profile; user re-designated the route target from a concrete relay to an aggregate while keeping the route.

Common situations: Reorganizing providers: a concrete relay used as a route target got converted into an aggregate; user assumes routing can load-balance through an aggregate; settings imported from another machine where the id now belongs to an aggregate.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16). Data as JSON: /api/errors/37f27090abf5a28f. Report an issue: GitHub.