BerriAI/litellm · error · ValueError

Template '{template_id}' not found

Error message

Template '{template_id}' not found

What it means

ValueError raised by GitLabPromptManager.render_template when the requested template_id is not present in the in-memory self.prompts dict. The manager only renders templates that were previously loaded from GitLab; it does not lazy-load inside render_template.

Source

Thrown at litellm/integrations/gitlab/gitlab_prompt_manager.py:211

                key, value = line.split(":", 1)
                key = key.strip()
                value = value.strip()
                if value.lower() in ["true", "false"]:
                    result[key] = value.lower() == "true"
                elif value.isdigit():
                    result[key] = int(value)
                elif value.replace(".", "").isdigit():
                    try:
                        result[key] = float(value)
                    except Exception:
                        result[key] = value
                else:
                    result[key] = value.strip("\"'")
        return result

    def render_template(self, template_id: str, variables: dict[str, Any] | None = None) -> str:
        if template_id not in self.prompts:
            raise ValueError(f"Template '{template_id}' not found")
        template: Final = self.prompts[template_id]
        jinja_template: Final = self.jinja_env.from_string(template.content)
        return jinja_template.render(**(variables or {}))

    def get_template(self, template_id: str) -> GitLabPromptTemplate | None:
        return self.prompts.get(template_id)

    def list_templates(self, *, recursive: bool = True) -> list[str]:
        """
        List available prompt IDs under prompts_path (no extension).
        Compatible with both list_files signatures:
        - list_files(directory_path=..., file_extension=..., recursive=...)
        - list_files(path=..., ref=None, recursive=...)
        """
        # First try the "new" signature (directory_path/file_extension)
        try:
            files = self.gitlab_client.list_files(
                directory_path=self.prompts_path,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Call load_all_prompts() first, or _load_prompt_from_gitlab(template_id), before render_template
  2. Verify the id via list_templates() — ids are file paths without the .prompt extension
  3. Check exact spelling/case of the id
  4. Prefer the higher-level get_prompt_template() which lazy-loads on miss

Example fix

# before
rendered = manager.render_template('greeting', {'name': 'A'})

# after
if 'greeting' not in manager.prompts:
    manager._load_prompt_from_gitlab('greeting')
rendered = manager.render_template('greeting', {'name': 'A'})
Defensive patterns

Strategy: validation

Validate before calling

if template_id not in manager.prompts:
    manager._load_prompt_from_gitlab(template_id)
assert template_id in manager.prompts, f"{template_id} unavailable"

Type guard

def is_loaded_template(manager, template_id: str) -> bool:
    """Narrow: True only if the id is loaded and renderable."""
    return isinstance(template_id, str) and template_id in manager.prompts

Try / catch

try:
    out = manager.render_template(tid, vars)
except ValueError as e:
    if "not found" in str(e):
        manager._load_prompt_from_gitlab(tid)
        out = manager.render_template(tid, vars)
    else:
        raise

Prevention

When it happens

Trigger: Calling render_template('my_prompt', vars) before _load_prompt_from_gitlab('my_prompt') or load_all_prompts() has populated it; using a template id with a different spelling/case than the file-derived id; after a failed silent load.

Common situations: Skipping the eager load step in initialization; ids derived from filenames (extension stripped) so 'greeting.prompt' must be rendered as 'greeting'; process restart losing in-memory cache while code assumes persistence.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/a22ba1a4950b14d4. Report an issue: GitHub.