{"record":{"id":"e9949b7006d9c855","repo":"can1357/oh-my-pi","slug":"provider-providername-model-missing-id","errorCode":null,"errorMessage":"Provider ${providerName}: model missing \"id\"","messagePattern":"Provider (.+?): model missing \"id\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/config/models-config.ts","lineNumber":94,"sourceCode":"\t\t\t\t\t: `Provider ${providerName}: \"apiKey\" is required when defining custom models unless auth is \"none\" or \"oauth\".`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (mode === \"models-config\" && config.discovery && !config.api && config.discovery.type !== \"proxy\") {\n\t\tthrow new Error(`Provider ${providerName}: \"api\" is required when discovery is enabled at provider level.`);\n\t}\n\n\tfor (const modelDef of models) {\n\t\tif (!hasProviderApi && !modelDef.api) {\n\t\t\tthrow new Error(\n\t\t\t\tmode === \"runtime-register\"\n\t\t\t\t\t? `Provider ${providerName}, model ${modelDef.id}: no \"api\" specified.`\n\t\t\t\t\t: `Provider ${providerName}, model ${modelDef.id}: no \"api\" specified. Set at provider or model level.`,\n\t\t\t);\n\t\t}\n\t\tif (!modelDef.id) {\n\t\t\tthrow new Error(`Provider ${providerName}: model missing \"id\"`);\n\t\t}\n\t\tif (mode === \"models-config\") {\n\t\t\tif (modelDef.contextWindow !== undefined && modelDef.contextWindow <= 0) {\n\t\t\t\tthrow new Error(`Provider ${providerName}, model ${modelDef.id}: invalid contextWindow`);\n\t\t\t}\n\t\t\tif (modelDef.maxTokens !== undefined && modelDef.maxTokens <= 0) {\n\t\t\t\tthrow new Error(`Provider ${providerName}, model ${modelDef.id}: invalid maxTokens`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport const ModelsConfigFile = new ConfigFile<ModelsConfig>(\"models\", {\n\tkind: \"deferred\",\n\tresolve: getModelsConfigSchema,\n}).withValidation(\"models\", config => {\n\tconst providers = config.providers ?? {};\n\tfor (const providerName in providers) {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/config/models-config.ts#L76-L112","documentation":"Thrown by validateProviderConfiguration when a model definition in a provider's models array has no \"id\" field. The id is the model's identity used for routing requests, catalog lookup, and display, so a model without one cannot be registered. Unlike the api check, this applies in both runtime-register and models-config modes.","triggerScenarios":"registerProvider called with a models array containing an entry missing id; models-config file parsed with a model object lacking the id key.","commonSituations":"YAML/JSON typo (\"model\" instead of \"id\"), copy-paste of a model entry where the id line was deleted, programmatically generated model lists where an empty/anonymous object slipped in.","solutions":["Add an \"id\" field to every model entry in the provider config","Check for YAML indentation mistakes that put id under the wrong object","Validate your models-config JSON/YAML against the schema before loading"],"exampleFix":"// before\n{ \"models\": [{ \"name\": \"gpt-x\", \"api\": \"openai-completions\" }] }\n// after\n{ \"models\": [{ \"id\": \"gpt-x\", \"api\": \"openai-completions\" }] }","handlingStrategy":"validation","validationCode":"function assertModelIds(cfg) {\n  (cfg.models ?? []).forEach((m, i) => {\n    if (typeof m.id !== 'string' || !m.id) throw new Error(`models[${i}].id missing`);\n  });\n}","typeGuard":"function hasId(m) { return typeof m === 'object' && m !== null && typeof m.id === 'string' && m.id.length > 0; }","tryCatchPattern":"try { registerProvider(cfg); } catch (e) { if (String(e).includes('model missing \"id\"')) { logger.error('Every model entry needs an id', { provider: cfg.name }); } else throw e; }","preventionTips":["Use a schema validator (zod/arktype) on provider configs before registration","Never build model entries by hand — map from a typed source list","Lint YAML configs for key typos (name vs id)"],"tags":["config","provider","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}