aaif-goose/goose · error
Failed to parse {}: {}
Error message
Failed to parse {}: {} What it means
goose scans the declarative-providers directory for *.json files and deserializes each into DeclarativeProviderConfig (a strict serde schema: required name/engine/display_name/base_url, typed models array, unknown setup fields rejected). When one file fails deserialization, the error embeds the full file path and the underlying serde message so you know exactly which JSON is broken and why.
Source
Thrown at crates/goose-providers/src/declarative.rs:290
let mut config = deserialize_provider_config(json)?;
resolve_config(&mut config)?;
Ok(config)
}
pub fn load_custom_providers(dir: &Path) -> Result<Vec<DeclarativeProviderConfig>> {
if !dir.exists() {
return Ok(Vec::new());
}
std::fs::read_dir(dir)?
.filter_map(|entry| {
let path = entry.ok()?.path();
(path.extension()? == "json").then_some(path)
})
.map(|path| {
let content = std::fs::read_to_string(&path)?;
deserialize_provider_config(&content)
.map_err(|e| anyhow::anyhow!("Failed to parse {}: {}", path.display(), e))
})
.collect()
}
pub fn from_json(
json: &str,
tls_config: Option<TlsConfig>,
key_resolver: impl KeyResolver,
) -> Result<Box<dyn Provider>> {
let config = config_from_json(json)?;
match config.engine {
ProviderEngine::OpenAI => openai::from_declarative_config(config, tls_config, key_resolver)
.map(|provider| Box::new(provider.build()) as Box<dyn Provider>),
ProviderEngine::Ollama => ollama::from_declarative_config(config, tls_config, key_resolver)
.map(|provider| Box::new(provider.build()) as Box<dyn Provider>),
ProviderEngine::Anthropic => {
anthropic::from_declarative_config(config, tls_config, key_resolver)View on GitHub (pinned to 3810898a74)
Solutions
- Read the message: it names the file and the serde error (e.g. 'missing field `engine` at line 3') — open that exact file and fix the cited field
- Validate the file against a known-good bundled provider JSON (same top-level keys: name, engine, display_name, base_url, models, env_vars...)
- Run it through a JSON linter (jq . file.json) to catch syntax errors first
- If the file isn't meant to be a provider, move it out of the scanned directory or rename the extension away from .json
Example fix
// before (broken file.json)
{ "name": "my-provider", "engine": "openai_compatible", "base_url": "https://api.x.com/v1" } // missing display_name
// after
{ "name": "my-provider", "engine": "openai_compatible", "display_name": "My Provider", "base_url": "https://api.x.com/v1", "models": [] } Defensive patterns
Strategy: try-catch
Validate before calling
fn provider_json_valid(path: &std::path::Path) -> anyhow::Result<()> {
let text = std::fs::read_to_string(path)?;
serde_json::from_str::<serde_json::Value>(&text)?; // syntax
deserialize_provider_config(&text)?; // schema
Ok(())
} Try / catch
// Don't let one bad file kill the whole scan: collect per-file outcomes, skip
// invalid files with a warning, and report them together:
let mut ok = Vec::new();
for path in json_files {
match try_load(&path) {
Ok(cfg) => ok.push(cfg),
Err(e) => eprintln!("warning: skipping {}: {e}", path.display()),
}
} Prevention
- Lint every custom provider JSON with deserialize_provider_config in CI before it lands in the providers dir
- Keep example/template files out of the scanned directory (different extension or directory)
- Pin provider JSON files in version control and review them like code — schema changes then surface in diffs
When it happens
Trigger: Any .json file in the scanned providers dir that: misses a required field ('engine', 'base_url', ...), has a wrong type ("context_limit": "4096" as string), an unknown field inside 'setup', invalid JSON syntax (trailing comma, unquoted key), or an engine value serde can't map.
Common situations: Hand-authored custom provider JSON with a typo'd or missing key; files edited with an editor that broke JSON syntax; copying a config snippet from docs for a different goose version whose schema changed; leaving a template/example file with placeholder values in the directory.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid provider type: {}
- Required environment variable {} is not set
- Invalid provider id: provider id cannot be empty
- Invalid provider id: {id}
- Provider '{}' has dynamic_models: false but no static models
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/25b27e7adf57d23d.
Report an issue: GitHub.