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

Provider '{}' has dynamic_models: false but no static models

Error message

Provider '{}' has dynamic_models: false but no static models listed; at least one entry in `models` is required.

What it means

Thrown by OpenAiProviderBuilder::from_declarative_config when a declarative provider entry sets dynamic_models: false but its models list is empty. With dynamic model fetching disabled and no static entries, the provider has no way to know which models exist, so construction is rejected up front instead of failing later at request time.

Source

Thrown at crates/goose-providers/src/openai.rs:870

        if !is_reserved_request_param_key(key) {
            object.insert(key.clone(), value.clone());
        }
    }
}

pub fn from_declarative_config(
    config: DeclarativeProviderConfig,
    tls_config: Option<TlsConfig>,
    key_resolver: impl KeyResolver,
) -> Result<OpenAiProviderBuilder> {
    let custom_models = if !config.models.is_empty() {
        Some(config.models.clone())
    } else {
        None
    };

    if config.dynamic_models == Some(false) && custom_models.is_none() {
        return Err(anyhow::anyhow!(
            "Provider '{}' has dynamic_models: false but no static models listed; \
             at least one entry in `models` is required.",
            config.name
        ));
    }

    let api_key = if config.api_key_env.is_empty() {
        None
    } else {
        match key_resolver.resolve_key(config.api_key_env.as_str()) {
            Ok(key) => Some(key),
            Err(err) => {
                if config.requires_auth {
                    anyhow::bail!("missing required key {}: {}", config.api_key_env, err);
                }
                None
            }
        }

View on GitHub (pinned to 3810898a74)

Solutions

  1. Add at least one model entry under 'models' for that provider, e.g. 'models: [{id: gpt-4o, context_limit: 128000}]'
  2. If dynamic fetching should stay enabled, remove 'dynamic_models: false' or set it to true so the provider queries the /models endpoint
  3. Check YAML indentation: 'models' must be a sibling of 'dynamic_models' under the same provider entry
  4. Validate the resolved config (print the parsed DeclarativeProviderConfig) to confirm models is non-empty

Example fix

# before
providers:
  my-gateway:
    dynamic_models: false

# after
providers:
  my-gateway:
    dynamic_models: false
    models:
      - id: my-model
        context_limit: 128000
Defensive patterns

Strategy: validation

Validate before calling

fn validate_provider(cfg: &DeclarativeProviderConfig) -> Result<(), String> {
    if cfg.dynamic_models == Some(false) && cfg.models.is_empty() {
        return Err(format!(
            "provider '{}' disables dynamic models but lists no models",
            cfg.name
        ));
    }
    Ok(())
}

Try / catch

if let Err(e) = validate_provider(&cfg) {
    eprintln!("config rejected: {e}");
    std::process::exit(2);
}

Prevention

When it happens

Trigger: A YAML/JSON declarative provider config that contains 'dynamic_models: false' (or `dynamic_models: false` in frontmatter) while the 'models' key is absent, empty, or mis-indented so it parses as empty.

Common situations: Users pin static models to avoid network calls to a /models endpoint (offline, air-gapped, or rate-limited gateways) but forget to list the models; or a YAML indentation mistake puts the models entries under a different key so they are silently dropped.

Related errors


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