can1357/oh-my-pi · error
Provider ${providerName}: "api" is required when registering
Error message
Provider ${providerName}: "api" is required when registering streamSimple. What it means
ModelRegistry.registerProvider enforces that a provider config supplying `streamSimple` (a custom streaming function) also declares `api`, because the runtime needs to know which wire API the stream function implements. Without `api` the registry cannot type or route the custom streamer, so it throws immediately.
Source
Thrown at packages/coding-agent/src/config/model-registry.ts:2524
if (activeSources.has(sourceId)) {
continue;
}
this.clearSourceRegistrations(sourceId);
this.#registeredProviderSources.delete(sourceId);
}
}
/**
* Register a provider dynamically (from extensions).
*
* If provider has models: replaces all existing models for this provider.
* If provider has only baseUrl/headers: overrides existing models' URLs.
* If provider has streamSimple: registers a custom API streaming function.
* If provider has oauth: registers OAuth provider for /login support.
*/
registerProvider(providerName: string, config: ProviderConfigInput, sourceId?: string): void {
if (config.streamSimple && !config.api) {
throw new Error(`Provider ${providerName}: "api" is required when registering streamSimple.`);
}
validateProviderConfiguration(
providerName,
{
baseUrl: config.baseUrl,
headers: config.headers,
apiKey: config.apiKey,
api: config.api,
oauthConfigured: Boolean(config.oauth),
models: (config.models ?? []) as ProviderValidationModel[],
},
"runtime-register",
);
if (config.streamSimple && config.api) {
const streamSimple = config.streamSimple;
registerCustomApi(config.api, streamSimple, sourceId, (model, context, options) =>View on GitHub (pinned to 9690622007)
Solutions
- Add the `api` field matching your streamSimple implementation's wire protocol to the ProviderConfigInput.
- If the stream function was accidental, remove `streamSimple` and rely on baseUrl/headers routing instead.
- Check the ProviderConfigInput type/docs for the accepted `api` values and pick the one your backend speaks.
Example fix
// before
registry.registerProvider("mygw", { streamSimple: myStream });
// after
registry.registerProvider("mygw", { api: "openai-completions", streamSimple: myStream }); Defensive patterns
Strategy: validation
Validate before calling
function assertStreamSimpleConfig(cfg: ProviderConfigInput): void {
if (cfg.streamSimple && !cfg.api) {
throw new Error('streamSimple requires "api"');
}
}
assertStreamSimpleConfig(input); // call before registerProvider Type guard
function hasApiForStreamSimple(cfg: ProviderConfigInput): cfg is ProviderConfigInput & { api: Api } {
return !cfg.streamSimple || typeof cfg.api === "string";
} Try / catch
try {
registry.registerProvider(name, cfg);
} catch (err) {
if (err instanceof Error && err.message.includes('"api" is required when registering streamSimple')) {
registry.registerProvider(name, { ...cfg, api: "openai-completions" });
} else throw err;
} Prevention
- Always pair streamSimple with an explicit api in the same config object.
- Model the config with a discriminated type that makes api mandatory when streamSimple is present.
- Validate provider input with assertStreamSimpleConfig before calling registerProvider.
- Keep custom-streamer examples updated so copied snippets include api.
When it happens
Trigger: Calling registerProvider(name, { streamSimple: fn, ... }) without `api` — e.g. an SDK user or plugin registers a custom streaming transport but forgets to specify which API dialect ("openai-completions", "anthropic-messages", etc.) it speaks.
Common situations: Writing a custom provider plugin that proxies a nonstandard backend; adapting an internal gateway; copying an older config example from before the api field was required for streamSimple.
Related errors
- Provider ${providerName}, model ${modelDef.id}: no "api" spe
- Provider ${providerName}: "api" is required when discovery i
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id wit
- ${name} path does not exist: ${trimmed}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7999643ef6c23f77.
Report an issue: GitHub.