{"record":{"id":"cfa77a46dd5cd420","repo":"n8n-io/n8n","slug":"at-least-one-category-must-be-defined","errorCode":null,"errorMessage":"At least one category must be defined","messagePattern":"At least one category must be defined","errorType":"exception","errorClass":"NodeOperationError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/TextClassifier.node.ts","lineNumber":200,"sourceCode":"\t\tconst batchSize = this.getNodeParameter('options.batching.batchSize', 0, 5) as number;\n\t\tconst delayBetweenBatches = this.getNodeParameter(\n\t\t\t'options.batching.delayBetweenBatches',\n\t\t\t0,\n\t\t\t0,\n\t\t) as number;\n\n\t\tconst llm = (await this.getInputConnectionData(\n\t\t\tNodeConnectionTypes.AiLanguageModel,\n\t\t\t0,\n\t\t)) as BaseLanguageModel;\n\n\t\tconst categories = this.getNodeParameter('categories.categories', 0, []) as Array<{\n\t\t\tcategory: string;\n\t\t\tdescription: string;\n\t\t}>;\n\n\t\tif (categories.length === 0) {\n\t\t\tthrow new NodeOperationError(this.getNode(), 'At least one category must be defined');\n\t\t}\n\n\t\tconst options = this.getNodeParameter('options', 0, {}) as {\n\t\t\tmultiClass: boolean;\n\t\t\tfallback?: string;\n\t\t\tsystemPromptTemplate?: string;\n\t\t\tenableAutoFixing: boolean;\n\t\t};\n\t\tconst multiClass = options?.multiClass ?? false;\n\t\tconst fallback = options?.fallback ?? 'discard';\n\n\t\tconst schemaEntries = categories.map((cat) => [\n\t\t\tcat.category,\n\t\t\tz\n\t\t\t\t.boolean()\n\t\t\t\t.describe(\n\t\t\t\t\t`Should be true if the input has category \"${cat.category}\" (description: ${cat.description})`,\n\t\t\t\t),","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/TextClassifier.node.ts#L182-L218","documentation":"Thrown by the Text Classifier node when the 'categories.categories' fixedCollection is empty. The classifier routes items into named categories via an LLM, so with zero categories defined there is nothing to classify against.","triggerScenarios":"User added no category rows to the Text Classifier's 'Categories' fixedCollection. The categories array length is 0 and the guard throws before any LLM call.","commonSituations":"User forgot to add categories; categories were cleared; workflow imported with the categories fixedCollection empty; user expected defaults but none exist for this node.","solutions":["Add at least one category row (with a name and description) under the Text Classifier's Categories setting.","If you want a catch-all, also configure the fallback 'other' option.","Re-import the workflow from a known-good export if categories were lost."],"exampleFix":"// before\nif (categories.length === 0) {\n  throw new NodeOperationError(this.getNode(), 'At least one category must be defined');\n}\n\n// after — instruct the user how to fix\nif (categories.length === 0) {\n  throw new NodeOperationError(this.getNode(), {\n    message: 'At least one category must be defined.',\n    description: 'Add category rows under Categories, each with a name and description.',\n  });\n}","handlingStrategy":"validation","validationCode":"const categories = this.getNodeParameter('categories.categories', 0, []) as Array<{ category: string; description: string }>;\nif (categories.length === 0) {\n  throw new Error('Add at least one category row with a name and description');\n}","typeGuard":"function hasCategories(c: unknown[]): c is Array<{ category: string; description: string }> {\n  return Array.isArray(c) && c.length > 0 && c.every((x) => typeof x.category === 'string');\n}","tryCatchPattern":null,"preventionTips":["Add at least one category row before running the node.","Configure the 'other' fallback if you want a catch-all bucket.","Validate workflow imports include the categories fixedCollection."],"tags":["configuration","parameter-validation","text-classifier","schema"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}