{"record":{"id":"1d7b7bd2e76d8b97","repo":"BerriAI/litellm","slug":"prompt-id-is-required-when-prompt-file-is-provided","errorCode":null,"errorMessage":"prompt_id is required when prompt_file is provided","messagePattern":"prompt_id is required when prompt_file is provided","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/integrations/dotprompt/prompt_manager.py","lineNumber":84,"sourceCode":"        self.jinja_env = ImmutableSandboxedEnvironment(\n            loader=DictLoader({}),\n            autoescape=select_autoescape([\"html\", \"xml\"]),\n            # Use Handlebars-style delimiters to match Dotprompt spec\n            variable_start_string=\"{{\",\n            variable_end_string=\"}}\",\n            block_start_string=\"{%\",\n            block_end_string=\"%}\",\n            comment_start_string=\"{#\",\n            comment_end_string=\"#}\",\n        )\n\n        # Load prompts from directory if provided\n        if self.prompt_directory:\n            self._load_prompts()\n\n        if self.prompt_file:\n            if not prompt_id:\n                raise ValueError(\"prompt_id is required when prompt_file is provided\")\n\n            template: Final = self._load_prompt_file(self.prompt_file, prompt_id)\n            self.prompts[prompt_id] = template\n\n        # Load prompts from JSON data if provided\n        if prompt_data:\n            self._load_prompts_from_json(prompt_data, prompt_id)\n\n    def _load_prompts(self) -> None:\n        \"\"\"Load all .prompt files from the prompt directory.\"\"\"\n        if not self.prompt_directory or not self.prompt_directory.exists():\n            raise ValueError(f\"Prompt directory does not exist: {self.prompt_directory}\")\n\n        prompt_files: Final = list(self.prompt_directory.glob(\"*.prompt\"))\n\n        for prompt_file in prompt_files:\n            try:\n                prompt_id = prompt_file.stem  # filename without extension","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/dotprompt/prompt_manager.py#L66-L102","documentation":"PromptManager.__init__ raises ValueError when prompt_file is given without prompt_id. Unlike prompt_directory (which derives ids from file stems) or prompt_data (keyed dicts), a single prompt file has no intrinsic id in this API, so the manager refuses to guess what key should map to self.prompts[prompt_id].","triggerScenarios":"PromptManager(prompt_file='prompts/greeting.prompt') with no prompt_id argument. Building the manager from a config dict where the id key is misspelled or dropped. Passing Path objects for prompt_file but forgetting the id is a separate positional/keyword arg.","commonSituations":"Switching from prompt_directory to a single-file setup and not realizing the id contract changes; YAML/env-driven config where prompt_id is optional and silently None; CI using a fixture prompt file without the id.","solutions":["Pass prompt_id alongside prompt_file: PromptManager(prompt_file=..., prompt_id='greeting')","Or switch to prompt_directory, which auto-registers every *.prompt file under its filename stem","Or supply prompt_data dicts keyed by the desired ids instead of a file","If config-driven, validate the config schema before constructing PromptManager"],"exampleFix":"# before\nmanager = PromptManager(prompt_file='prompts/greeting.prompt')\n\n# after\nmanager = PromptManager(prompt_file='prompts/greeting.prompt', prompt_id='greeting')","handlingStrategy":"validation","validationCode":"if prompt_file and not prompt_id:\n    raise ValueError(f'prompt_id required when loading prompt_file={prompt_file}')\nmanager = PromptManager(prompt_id=prompt_id, prompt_file=prompt_file)","typeGuard":null,"tryCatchPattern":"try:\n    manager = PromptManager(prompt_file=path, prompt_id=prompt_id)\nexcept ValueError as e:\n    if 'prompt_id is required when prompt_file' in str(e):\n        prompt_id = Path(path).stem  # derive an id and retry\n        manager = PromptManager(prompt_file=path, prompt_id=prompt_id)\n    else:\n        raise","preventionTips":["Treat prompt_file and prompt_id as a paired setting in config validation","Prefer prompt_directory for bulk loads — ids come from filenames automatically","Unit-test manager construction with your production config shape"],"tags":["litellm","dotprompt","prompt","file-loading","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}