zylon-ai/private-gpt · error · ValueError
Template {template_name} does not have a source or filename.
Error message
Template {template_name} does not have a source or filename. What it means
`PromptTemplate.get_template_str` extracts a template's text from a Jinja environment template: it prefers `template.source`, falls back to reading `template.filename` from disk, and raises `ValueError` when the template object has neither a usable `source` attribute nor a truthy `filename`. This happens with Jinja Template objects created from non-filesystem loaders or dict loaders that strip these attributes.
Source
Thrown at private_gpt/components/prompts/prompt_template.py:36
trim_blocks=True,
lstrip_blocks=True,
extensions=["jinja2.ext.do"],
)
def get_template(self, template_name: str) -> Template:
return self.env.get_template(template_name)
def get_template_str(self, template_name: str) -> str:
"""Get the template string from the template name."""
template = self.get_template(template_name)
if hasattr(template, "source"):
return str(template.source)
elif hasattr(template, "filename") and template.filename:
template_path = Path(template.filename)
with open(template_path, encoding="utf-8") as f:
return f.read()
else:
raise ValueError(
f"Template {template_name} does not have a source or filename."
)
def create_prompt_template(
self,
template_name: str,
**template_kwargs: Any,
) -> BasePromptTemplate:
template = self.get_template(template_name)
template_str = self.get_template_str(template_name)
def process_value(v: Any) -> Any:
if isinstance(v, list):
return [process_value(value) for value in v]
elif isinstance(v, dict):
return {
process_value(key): process_value(val) for key, val in v.items()
}View on GitHub (pinned to 4a030776a3)
Solutions
- Use the standard file-based loader so resolved templates carry `filename`
- Ensure the loader populates `source` on templates (e.g. wrap DictLoader values so templates keep their source)
- Force template compile/resolve via `env.get_template(name)` before calling `get_template_str`, since the code path already calls `get_template` first
Example fix
# before
env = Environment(loader=DictLoader({"my.prompt": "text {{x}}"}))
# template lacks source/filename -> ValueError
# after
env = Environment(
loader=FileSystemLoader("private_gpt/components/prompts/templates")
) Defensive patterns
Strategy: validation
Validate before calling
template = prompt_env.get_template(name)
if not (getattr(template, "source", None) or getattr(template, "filename", None)):
raise ValueError(f"loader for {name!r} strips source/filename; use a file-based loader") Type guard
def template_is_readable(template: Any) -> bool:
return bool(getattr(template, "source", None)) or bool(getattr(template, "filename", None)) Try / catch
try:
template_str = prompts.get_template_str(name)
except ValueError as e:
if "does not have a source or filename" in str(e):
raise ConfigurationError("prompt loader must keep source or filename") from e
raise Prevention
- Use FileSystemLoader for prompt templates; avoid dict/string loaders on paths that call get_template_str
- Test every registered template name through get_template_str in CI
When it happens
Trigger: Loading prompts via a custom Jinja loader (e.g. DictLoader) whose Template objects lack `source`/`filename`; a template compiled from a string without source retention; calling `get_template_str`/`create_prompt_template` for a template name resolved through such an environment.
Common situations: Customizing the prompt environment or loaders; embedding prompts in code instead of files; Jinja version behavior differences in what attributes a lazily-loaded Template exposes before rendering.
Related errors
- Invalid system item in list: {item}
- Unknown condense strategy: {strategy}
- Audio blocks found but no audio-capable LLM provided.
- Code execution provider '{name}' is not registered. Availabl
- Unsupported semaphore mode: {mode!r}. Available: {', '.join(
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/7b0a44f9c54df903.
Report an issue: GitHub.