{"record":{"id":"2f3d331bcf44c268","repo":"run-llama/llama_index","slug":"num-keywords-must-be-1","errorCode":null,"errorMessage":"num_keywords must be >= 1","messagePattern":"num_keywords must be >= 1","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/extractors/metadata_extractors.py","lineNumber":213,"sourceCode":"\n    prompt_template: str = Field(\n        default=DEFAULT_KEYWORD_EXTRACT_TEMPLATE,\n        description=\"Prompt template to use when generating keywords.\",\n    )\n\n    def __init__(\n        self,\n        llm: Optional[LLM] = None,\n        # TODO: llm_predictor arg is deprecated\n        llm_predictor: Optional[LLM] = None,\n        keywords: int = 5,\n        prompt_template: str = DEFAULT_KEYWORD_EXTRACT_TEMPLATE,\n        num_workers: int = DEFAULT_NUM_WORKERS,\n        **kwargs: Any,\n    ) -> None:\n        \"\"\"Init params.\"\"\"\n        if keywords < 1:\n            raise ValueError(\"num_keywords must be >= 1\")\n\n        super().__init__(\n            llm=llm or llm_predictor or Settings.llm,\n            keywords=keywords,\n            prompt_template=prompt_template,\n            num_workers=num_workers,\n            **kwargs,\n        )\n\n    @classmethod\n    def class_name(cls) -> str:\n        return \"KeywordExtractor\"\n\n    async def _aextract_keywords_from_node(self, node: BaseNode) -> Dict[str, str]:\n        \"\"\"Extract keywords from a node and return it's metadata dict.\"\"\"\n        if self.is_text_node_only and not isinstance(node, TextNode):\n            return {}\n","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/extractors/metadata_extractors.py#L195-L231","documentation":"Raised by KeywordExtractor.__init__ when the keywords parameter (number of keywords the LLM should extract per node, default 5) is less than 1. The count is baked into prompt_template, so a non-positive count is rejected immediately in __init__.","triggerScenarios":"Constructing KeywordExtractor(keywords=0), typically from a config value, CLI flag, or computed expression that evaluates to zero or a negative number.","commonSituations":"YAML/JSON pipeline configs with keywords: 0; env-var parsing like int(os.environ.get('NUM_KEYWORDS', '0')); dynamic sizing that yields 0 for tiny documents.","solutions":["Pass keywords >= 1, e.g. KeywordExtractor() for the default of 5.","Clamp at the config boundary: keywords = max(1, cfg['keywords']).","To disable keyword extraction, exclude the extractor from the pipeline instead of setting 0."],"exampleFix":"# before\nextractor = KeywordExtractor(keywords=int(cfg.get(\"keywords\", 0)))\n\n# after\nextractor = KeywordExtractor(keywords=max(1, int(cfg.get(\"keywords\", 5))))","handlingStrategy":"validation","validationCode":"num_keywords = int(config.get(\"keywords\", 5))\nif num_keywords < 1:\n    raise ValueError(f\"keywords must be >= 1, got {num_keywords}\")\nextractor = KeywordExtractor(keywords=num_keywords)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp keyword counts with max(1, value) at the config boundary.","Avoid int() defaults of 0 when parsing optional settings.","Drop the extractor from the pipeline to disable it, never zero the count."],"tags":["validation","configuration","constructor","off-by-one"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}