{"record":{"id":"8b7a9ab50a96beed","repo":"n8n-io/n8n","slug":"model-id-is-required","errorCode":null,"errorMessage":"Model ID is required","messagePattern":"Model ID is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/runtime/model/model-factory.ts","lineNumber":227,"sourceCode":"\t\t\t})(model);\n\t\t},\n\t},\n};\n\nconst SUPPORTED_PROVIDERS = Object.keys(LANGUAGE_PROVIDERS).join(', ');\n\n/**\n * Provider packages are loaded dynamically via require() so only the\n * provider needed at runtime must be installed.\n */\nexport function createModel(config: ModelConfig, fetch?: FetchFn): LanguageModel {\n\tif (isLanguageModel(config)) {\n\t\treturn config;\n\t}\n\n\tconst rawId = typeof config === 'string' ? config : config.id;\n\tif (!rawId || rawId.trim() === '') {\n\t\tthrow new Error('Model ID is required');\n\t}\n\n\tconst slashIndex = rawId.indexOf('/');\n\tif (slashIndex <= 0) {\n\t\tthrow new Error(`Invalid model ID \"${rawId}\": expected \"provider/model-name\" format`);\n\t}\n\tconst provider = rawId.slice(0, slashIndex) as ProviderId;\n\tconst modelName = rawId.slice(slashIndex + 1);\n\n\tconst entry = LANGUAGE_PROVIDERS[provider];\n\tif (!entry) {\n\t\tthrow new Error(\n\t\t\t`Unsupported provider: \"${provider}\". Supported providers: ${SUPPORTED_PROVIDERS}`,\n\t\t);\n\t}\n\n\t// Collect credential fields: strip `id`, pass the rest to Zod validation.\n\tlet credFields: Record<string, unknown> = {};","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/runtime/model/model-factory.ts#L209-L245","documentation":"`createModel` accepts a model config as either a string (`\"provider/model\"`) or an object (`{ id: \"provider/model\", ...creds }`). It extracts `rawId` and throws when the ID is empty, whitespace-only, or absent. Without a model ID the factory cannot resolve a provider or instantiate a language model.","triggerScenarios":"Calling `createModel('')`, `createModel({ id: '' })`, `createModel({ id: '   ' })`, or `createModel({})` (no `id` field at all). Also triggered when a credential resolution layer passes an empty model string.","commonSituations":"A credential/model configuration UI saved an empty model field. An environment variable or settings key for the model was not set, defaulting to empty string. The model ID was trimmed to empty by input sanitization. Instance AI config emitted `{ id: '', url: '...' }`.","solutions":["Check the value being passed to `.model()` or `createModel()` — log it before the call.","Ensure your model configuration source (env var, DB row, settings) has a non-empty `provider/model-name` value.","Add a UI-level or config-level validation that rejects empty model IDs before they reach the runtime.","If the model comes from user input, default to a known-good model when blank rather than passing empty through."],"exampleFix":"// before:\nconst model = createModel(config.modelId); // config.modelId is ''\n\n// after:\nconst modelId = config.modelId || 'openai/gpt-4o';\nif (!modelId.trim()) throw new Error('Model ID must be configured');\nconst model = createModel(modelId);","handlingStrategy":"validation","validationCode":"function validateModelId(id: string | undefined): string {\n  if (!id || id.trim() === '') {\n    throw new Error('Model ID must be a non-empty \"provider/model-name\" string');\n  }\n  return id;\n}\n\n// Before calling createModel:\nconst modelId = validateModelId(config.modelId);\nconst model = createModel(modelId);","typeGuard":"function isNonEmptyModelId(id: unknown): id is string {\n  return typeof id === 'string' && id.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate model IDs at the configuration/UI layer before they reach the runtime.","Set a sensible default model in your config schema so empty values never propagate.","Use env-var validation (e.g. Zod) for model settings at startup."],"tags":["model-config","validation","configuration","provider"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}