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

When building the Ollama provider from a declarative config, goose derives the static model list from the 'models' array (custom_models is None exactly when 'models' is empty) and normally falls back to querying the Ollama /api/tags endpoint for dynamic discovery. Setting "dynamic_models": false turns discovery off, so an empty 'models' list would leave the provider with literally no models — this error refuses that contradiction at construction time.

Source

Thrown at crates/goose-providers/src/ollama.rs:288

pub fn from_declarative_config(
    config: DeclarativeProviderConfig,
    tls_config: Option<TlsConfig>,
    key_resolver: impl KeyResolver,
) -> Result<OllamaProviderBuilder> {
    let custom_models = if !config.models.is_empty() {
        Some(
            config
                .models
                .iter()
                .map(|m| m.name.clone())
                .collect::<Vec<String>>(),
        )
    } 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 timeout = Duration::from_secs(config.timeout_seconds.unwrap_or(OLLAMA_TIMEOUT));

    let base_has_scheme =
        config.base_url.starts_with("http://") || config.base_url.starts_with("https://");
    let base = if base_has_scheme {
        config.base_url.clone()
    } else {
        format!("http://{}", config.base_url)
    };

    let mut base_url = Url::parse(&base)
        .map_err(|e| anyhow::anyhow!("Invalid base URL '{}': {}", config.base_url, e))?;

View on GitHub (pinned to 3810898a74)

Solutions

  1. List the models you want exposed: "models": [{"name": "llama3.2", "context_limit": 131072, "reasoning": false}, ...]
  2. Or drop "dynamic_models": false entirely — the default discovers models from the running Ollama server
  3. If the goal is filtering, keep dynamic_models on and list models (custom models act as the allowlist) or use skip_canonical_filtering as appropriate

Example fix

// before
{ "name": "my-ollama", "engine": "ollama", "base_url": "http://localhost:11434",
  "dynamic_models": false, "models": [] }

// after
{ "name": "my-ollama", "engine": "ollama", "base_url": "http://localhost:11434",
  "dynamic_models": false,
  "models": [{"name": "llama3.2", "context_limit": 131072, "reasoning": false}] }
Defensive patterns

Strategy: validation

Validate before calling

fn ollama_config_valid(cfg: &DeclarativeProviderConfig) -> bool {
    !(cfg.dynamic_models == Some(false) && cfg.models.is_empty())
}

Try / catch

if !ollama_config_valid(&cfg) {
    return Err(anyhow!("'{}' pins models (dynamic_models=false) but lists none; add a models[] entry or drop the flag", cfg.name));
}
ollama::from_declarative_config(cfg, tls, resolver)?;

Prevention

When it happens

Trigger: A custom Ollama provider JSON with "dynamic_models": false and a missing or empty "models": [] array — e.g. someone pinned an Ollama server version and disabled discovery but never listed the models to expose.

Common situations: Copying a declarative JSON template where 'models' was pre-cleared for dynamic setups, then flipping dynamic_models to false; intentionally hiding unwanted auto-discovered models but forgetting to enumerate the wanted ones; YAML-to-JSON conversion dropping an empty array field entirely (same effect as empty).

Related errors


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