{"record":{"id":"8e30b021d967280c","repo":"feder-cr/Jobs_Applier_AI_Agent_AIHawk","slug":"chain-not-defined-for-section-section-name","errorCode":null,"errorMessage":"Chain not defined for section '{section_name}'","messagePattern":"Chain not defined for section '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/libs/llm_manager.py","lineNumber":602,"sourceCode":"                }\n            )\n            output = self._clean_llm_output(raw_output)\n            logger.debug(f\"Cover letter generated: {output}\")\n            return output\n        resume_section = getattr(self.resume, section_name, None) or getattr(\n            self.job_application_profile, section_name, None\n        )\n        if resume_section is None:\n            logger.error(\n                f\"Section '{section_name}' not found in either resume or job_application_profile.\"\n            )\n            raise ValueError(\n                f\"Section '{section_name}' not found in either resume or job_application_profile.\"\n            )\n        chain = chains.get(section_name)\n        if chain is None:\n            logger.error(f\"Chain not defined for section '{section_name}'\")\n            raise ValueError(f\"Chain not defined for section '{section_name}'\")\n        raw_output = chain.invoke(\n            {RESUME_SECTION: resume_section, QUESTION: question}\n        )\n        output = self._clean_llm_output(raw_output)\n        logger.debug(f\"Question answered: {output}\")\n        return output\n\n    def answer_question_numeric(\n        self, question: str, default_experience: str = 3\n    ) -> str:\n        logger.debug(f\"Answering numeric question: {question}\")\n        func_template = self._preprocess_template_string(\n            prompts.numeric_question_template\n        )\n        prompt = ChatPromptTemplate.from_template(func_template)\n        chain = prompt | self.llm_cheap | StrOutputParser()\n        raw_output_str = chain.invoke(\n            {","sourceCodeStart":584,"sourceCodeEnd":620,"githubUrl":"https://github.com/feder-cr/Jobs_Applier_AI_Agent_AIHawk/blob/79155b52faccfbd19b834680af285eac70dd2df4/src/libs/llm_manager.py#L584-L620","documentation":"Even when the section exists in the data, answer_question_textual_wide_range needs an LCEL chain per section (chains.get(section_name)) to answer the question. If the dict has no chain registered under the extracted name, a ValueError is raised because there is no way to generate an answer.","triggerScenarios":"The extracted section name (from the LLM reply, lowercased and underscored) has no matching key in the chains mapping, e.g. chains was built for a subset of sections, or a section name normalization mismatch ('salary_expectations' vs 'salary').","commonSituations":"Customizing the chains dict without adding entries for all regex-recognized sections, renaming chain keys during refactoring, or schema changes introducing new sections.","solutions":["Register a chain for every section name the regex can produce: the keys of chains must cover personal_info, skills, education, experience_details, projects, availability, salary_expectations, certifications, languages, interests, cover_letter.","Check for normalization mismatches: extracted names are lowercased with spaces replaced by underscores; align chain keys to that convention.","If a section intentionally has no chain, catch the ValueError and fall back to a generic QA chain."],"exampleFix":"# before\nchains = {'skills': skills_chain}\n# after\nchains = {\n    'skills': skills_chain,\n    'education': education_chain,\n    'experience_details': experience_chain,\n    'certifications': certifications_chain,\n    # ... one entry per recognized section\n}","handlingStrategy":"validation","validationCode":"REQUIRED_CHAINS = {'personal_info','skills','education','experience_details','projects','availability','salary_expectations','certifications','languages','interests','cover_letter'}\nassert REQUIRED_CHAINS <= set(chains), f'missing chains: {REQUIRED_CHAINS - set(chains)}'","typeGuard":"def chains_complete(chains: dict) -> bool:\n    REQUIRED = {'personal_info','skills','education','experience_details','projects','availability','salary_expectations','certifications','languages','interests','cover_letter'}\n    return REQUIRED.issubset(chains.keys())","tryCatchPattern":"try:\n    ans = llm_manager.answer_question_textual_wide_range(q)\nexcept ValueError as e:\n    if 'Chain not defined' in str(e):\n        ans = generic_chain.invoke({'resume_section': '', 'question': q})\n    else:\n        raise","preventionTips":["Keep the chains registry in one place with an assertion that it covers every recognized section.","After renaming a chain key, grep the section-name normalization (lower + underscore) to stay consistent."],"tags":["python","llm","chain-registry","missing-mapping"],"backgroundTag":"missing-registry-entry","analyzedSha":"79155b52faccfbd19b834680af285eac70dd2df4","analyzedAt":"2026-08-28T14:10:26.659Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}