Goose Custom Provider Context Limit Bug

Date: 2026-05-13
Issue: Custom provider context_limit is ignored; goose always shows 0/128k instead of the configured value (e.g., 204800).


Symptom

When using a custom provider like custom_minimax with model MiniMax-M2.7 and context_limit: 204800, goose displays:

  ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 0% 0/128k

instead of the expected 0/200k.


Root Cause

ModelConfig::with_canonical_limits at crates/goose/src/model.rs:113-136 only resolves context limits from two sources:

  1. Canonical model registry — built-in providers (openai, anthropic, google, etc.)
  2. Predefined models — from the GOOSE_PREDEFINED_MODELS environment variable

It never checks the models array inside declarative/custom provider JSON files (~/.config/goose/custom_providers/*.json).

When the model name (MiniMax-M2.7) is unknown to both sources, context_limit stays None, and ModelConfig::context_limit() falls back to DEFAULT_CONTEXT_LIMIT = 128_000 (crates/goose/src/model.rs:8).

Affected code paths

FileLinesPurpose
crates/goose-cli/src/session/builder.rs385-391Builds ModelConfig when starting a CLI session
crates/goose-cli/src/commands/term.rs293-304Prints the initial status bar (0/128k)
crates/goose-server/src/routes/agent.rs576-585Builds ModelConfig in the Desktop/server route
crates/goose/src/providers/provider_registry.rs28-31create_with_default_model for default model selection

All of these call ModelConfig::new(...).with_canonical_limits(provider_name), which bypasses custom provider configs.


Where models IS used (and where it is not)

The models array in ~/.config/goose/custom_providers/custom_minimax.json is not completely useless, but its context_limit is ignored at runtime.

Used

LocationPurpose
provider_registry.rs:87-91Sets default_model from models.first()
provider_registry.rs:92-103Populates ProviderMetadata.known_models
goose-server/src/routes/config_management.rs:393Returns model list to Desktop UI
goose-cli/src/commands/configure.rs:449Shows models during goose configure

NOT used

What is missingWhere it should happen
models[].context_limit -> ModelConfig.context_limitModelConfig::with_canonical_limits

Workarounds (no code changes)

Option 1: GOOSE_CONTEXT_LIMIT environment variable

Highest priority. Overrides everything, including canonical limits.

export GOOSE_CONTEXT_LIMIT=204800
goose session

Validation: must be > 4096.

Option 2: GOOSE_PREDEFINED_MODELS environment variable

Model-scoped fallback. Checked after canonical registry, before the 128k default.

export GOOSE_PREDEFINED_MODELS='[{"name":"MiniMax-M2.7","context_limit":204800}]'
goose session

Multiple models:

export GOOSE_PREDEFINED_MODELS='[
  {"name":"MiniMax-M2.7","context_limit":204800},
  {"name":"MiniMax-Other","context_limit":128000}
]'

With provider-specific request parameters:

export GOOSE_PREDEFINED_MODELS='[{
  "name": "MiniMax-M2.7",
  "context_limit": 204800,
  "request_params": {
    "anthropic_beta": "token-efficient-tools-2025-02-19"
  }
}]'

Note: GOOSE_PREDEFINED_MODELS is read via std::env::var directly (model.rs:21). It cannot be set in ~/.config/goose/config.yaml; it must be an environment variable.

Option 3: Wrapper script

#!/bin/bash
export GOOSE_CONTEXT_LIMIT=204800
exec goose "$@"

Relevant source locations

FileLine(s)Description
crates/goose/src/model.rs8DEFAULT_CONTEXT_LIMIT = 128_000
crates/goose/src/model.rs19-35GOOSE_PREDEFINED_MODELS parser
crates/goose/src/model.rs78-110ModelConfig::new_base — reads GOOSE_CONTEXT_LIMIT
crates/goose/src/model.rs113-136ModelConfig::with_canonical_limitsthe buggy function
crates/goose/src/model.rs277-279context_limit() — returns 128_000 fallback
crates/goose/src/config/declarative_providers.rs307-341load_provider — loads custom provider JSON (not called by with_canonical_limits)
crates/goose/src/providers/provider_registry.rs92-103Copies models into ProviderMetadata.known_models
crates/goose-cli/src/commands/term.rs293-304Status bar context limit computation
crates/goose-cli/src/session/builder.rs385-391Session ModelConfig creation

Proper fix (requires code change)

In ModelConfig::with_canonical_limits, after the predefined-models check, add a fallback that loads the declarative provider config and searches its models array:

#![allow(unused)]
fn main() {
// Try filling remaining gaps from declarative/custom providers
if self.context_limit.is_none() {
    if let Ok(loaded_provider) =
        crate::config::declarative_providers::load_provider(provider_name)
    {
        if let Some(model_info) = loaded_provider
            .config
            .models
            .iter()
            .find(|m| m.name == self.model_name)
        {
            self.context_limit = Some(model_info.context_limit);
        }
    }
}
}

This would fix the bug for CLI, server, and default-model creation paths in one place.