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

  1. Set "api" on the provider config so all its models inherit it
  2. Or set "api" on each model definition that lacks it
  3. If using provider-level discovery, either specify api or set discovery.type to "proxy"
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ebe59e8247752219. Report an issue: GitHub.