can1357/oh-my-pi · error
Provider ${providerName}, model ${modelDef.id}: no "api" spe
Error message
Provider ${providerName}, model ${modelDef.id}: no "api" specified. / Provider ${providerName}, model ${modelDef.id}: no "api" specified. Set at provider or model level. What it means
Thrown by validateProviderConfiguration when a model definition has no "api" field and the provider itself does not declare one. The "api" field selects which wire protocol (e.g. openai-completions, anthropic-messages) the client uses to talk to the model, so without it the provider cannot be built. The message differs by mode: runtime-register gets the short form, models-config parsing gets a hint that api can be set at provider or model level. A provider-level discovery of type "proxy" is also exempt.
Source
Thrown at packages/coding-agent/src/config/models-config.ts:87
mode === "runtime-register"
? !config.apiKey && !config.oauthConfigured
: !config.apiKey && (config.auth ?? "apiKey") !== "none" && (config.auth ?? "apiKey") !== "oauth";
if (requiresAuth) {
throw new Error(
mode === "runtime-register"
? `Provider ${providerName}: "apiKey" or "oauth" is required when defining models.`
: `Provider ${providerName}: "apiKey" is required when defining custom models unless auth is "none" or "oauth".`,
);
}
}
if (mode === "models-config" && config.discovery && !config.api && config.discovery.type !== "proxy") {
throw new Error(`Provider ${providerName}: "api" is required when discovery is enabled at provider level.`);
}
for (const modelDef of models) {
if (!hasProviderApi && !modelDef.api) {
throw new Error(
mode === "runtime-register"
? `Provider ${providerName}, model ${modelDef.id}: no "api" specified.`
: `Provider ${providerName}, model ${modelDef.id}: no "api" specified. Set at provider or model level.`,
);
}
if (!modelDef.id) {
throw new Error(`Provider ${providerName}: model missing "id"`);
}
if (mode === "models-config") {
if (modelDef.contextWindow !== undefined && modelDef.contextWindow <= 0) {
throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid contextWindow`);
}
if (modelDef.maxTokens !== undefined && modelDef.maxTokens <= 0) {
throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid maxTokens`);
}
}
}
}View on GitHub (pinned to 9690622007)
Solutions
- Set "api" on the provider config so all its models inherit it
- Or set "api" on each model definition that lacks it
- If using provider-level discovery, either specify api or set discovery.type to "proxy"
- Check the model catalog for the correct api value for your endpoint type
Example fix
// before
{ "providers": { "my-llm": { "baseUrl": "http://localhost:8080", "models": [{ "id": "m1" }] } } }
// after
{ "providers": { "my-llm": { "baseUrl": "http://localhost:8080", "api": "openai-completions", "models": [{ "id": "m1" }] } } } Defensive patterns
Strategy: validation
Validate before calling
function assertProviderApi(cfg) {
if (!cfg.api && !(cfg.models ?? []).every(m => m.api))
throw new Error(`Provider ${cfg.name}: set "api" at provider or model level`);
} Type guard
function hasApi(cfg) { return typeof cfg.api === 'string' && cfg.api.length > 0; } Try / catch
try { registerProvider(cfg); } catch (e) { if (String(e).includes('no "api" specified')) { logger.error('Add api to provider or model config', { provider: cfg.name }); } else throw e; } Prevention
- Always set api at the provider level when defining multiple models
- Copy provider templates that include api from the docs
- Run config validation before deployment
When it happens
Trigger: Calling registerProvider (runtime) with models lacking api and no provider-level api; or loading a models-config file whose provider entry omits api on both provider and each model while discovery is absent or non-proxy.
Common situations: Hand-written custom provider entries copied from docs that assume a provider-level api; provider configs migrated from older versions where api defaulted; JSON/YAML models-config with models listed but api only implied.
Related errors
- Provider ${providerName}: model missing "id"
- Failed to load tree-sitter language: {err}
- Destination option ${key} must be a string
- Destination option ${key} must be a finite number
- Destination option ${key} must be a boolean
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ebe59e8247752219.
Report an issue: GitHub.