{"record":{"id":"7b244a16d2980df7","repo":"run-llama/llama_index","slug":"prompt-key-key-cannot-contain","errorCode":null,"errorMessage":"Prompt key {key} cannot contain ':'.","messagePattern":"Prompt key (.+?) cannot contain ':'\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/prompts/mixin.py","lineNumber":34,"sourceCode":"    \"\"\"\n    Prompt mixin.\n\n    This mixin is used in other modules, like query engines, response synthesizers.\n    This shows that the module supports getting, setting prompts,\n    both within the immediate module as well as child modules.\n\n    \"\"\"\n\n    def _validate_prompts(\n        self,\n        prompts_dict: PromptDictType,\n        module_dict: PromptMixinType,\n    ) -> None:\n        \"\"\"Validate prompts.\"\"\"\n        # check if prompts_dict, module_dict has restricted \":\" token\n        for key in prompts_dict:\n            if \":\" in key:\n                raise ValueError(f\"Prompt key {key} cannot contain ':'.\")\n\n        for key in module_dict:\n            if \":\" in key:\n                raise ValueError(f\"Prompt key {key} cannot contain ':'.\")\n\n    def get_prompts(self) -> Dict[str, BasePromptTemplate]:\n        \"\"\"Get a prompt.\"\"\"\n        prompts_dict = self._get_prompts()\n        module_dict = self._get_prompt_modules()\n        self._validate_prompts(prompts_dict, module_dict)\n\n        # avoid modifying the original dict\n        all_prompts = deepcopy(prompts_dict)\n        for module_name, prompt_module in module_dict.items():\n            # append module name to each key in sub-modules by \":\"\n            for key, prompt in prompt_module.get_prompts().items():\n                all_prompts[f\"{module_name}:{key}\"] = prompt\n        return all_prompts","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/prompts/mixin.py#L16-L52","documentation":"PromptMixin._validate_prompts (prompts/mixin.py) rejects any prompt key containing ':' in the dict returned by _get_prompts(). ':' is the reserved namespace separator used by get_prompts() to flatten sub-module prompts into keys like 'response_synthesizer:text_qa_template', so a raw ':' inside your own key would make the flattened namespace ambiguous and un-parseable by update_prompts().","triggerScenarios":"Implementing a component's _get_prompts() (or _get_prompt_modules()) and returning a dict whose key literally contains ':', e.g. {'my:prompt': SomeTemplate}. The error fires the moment get_prompts() is called on the component — including when it is embedded in a query engine / index whose get_prompts() recurses into it.","commonSituations":"Custom query engines or LLMs added to the codebase with ad-hoc prompt names that embed paths ('agent:system'), copy-pasted prompt identifiers from config files, or dynamically generated keys joined with ':'. Surfaces as soon as the user calls engine.get_prompts() or passes the component into a higher-level llama-index pipeline.","solutions":["Rename the key to remove ':' — use '_', '-', or '.' instead: {'my_prompt': ...} or {'agent.system': ...}.","If the intent was namespacing, model it properly: return the prompt from a sub-component and let get_prompts() build the 'module:key' name for you.","If keys come from external config, sanitize them (key.replace(':', '_')) when building the prompts dict.","Add a unit test asserting no key in _get_prompts()/_get_prompt_modules() contains ':' so regressions surface at test time, not at runtime."],"exampleFix":"# before\nclass MyQueryEngine(CustomQueryEngine):\n    def _get_prompts(self):\n        return {\"retriever:top_k\": self.retriever_prompt}  # -> ValueError\n\n# after\nclass MyQueryEngine(CustomQueryEngine):\n    def _get_prompts(self):\n        return {\"retriever_top_k\": self.retriever_prompt}  # no ':' anywhere","handlingStrategy":"validation","validationCode":"def validate_prompt_keys(prompts: dict) -> None:\n    bad = [k for k in prompts if \":\" in k]\n    if bad:\n        raise KeyError(f\"prompt keys must not contain ':' (reserved): {bad}\")\n\n# in your component:\n# validate_prompt_keys(self._get_prompts())","typeGuard":"def has_clean_prompt_keys(prompts: dict) -> bool:\n    return all(\":\" not in k for k in prompts)","tryCatchPattern":null,"preventionTips":["Treat ':' in prompt keys as a reserved namespace separator owned by the framework.","Use '_' or '.' for hierarchy in your own key names.","Add a test asserting all keys from _get_prompts()/_get_prompt_modules() are ':'-free."],"tags":["llama-index","prompts","prompt-mixin","naming","validation"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}