{"record":{"id":"40f0ec3c04a6f88f","repo":"affaan-m/ECC","slug":"template-content-must-be-a-non-empty-string","errorCode":null,"errorMessage":"Template content must be a non-empty string","messagePattern":"Template content must be a non-empty string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llm/prompt/templates/__init__.py","lineNumber":14,"sourceCode":"\"\"\"Provider-specific prompt template helpers.\"\"\"\n\nfrom __future__ import annotations\n\n_TEMPLATE_REGISTRY: dict[str, str] = {}\nTEMPLATES = _TEMPLATE_REGISTRY\n\n\ndef _validate_template_input(name: str, template: str | None = None) -> None:\n    \"\"\"Validate template registry inputs before mutating the registry.\"\"\"\n    if not isinstance(name, str) or not name.strip():\n        raise ValueError(\"Template name must be a non-empty string\")\n    if template is not None and (not isinstance(template, str) or not template.strip()):\n        raise ValueError(\"Template content must be a non-empty string\")\n\n\ndef register_template(name: str, template: str) -> None:\n    \"\"\"Register or replace a named prompt template.\"\"\"\n    _validate_template_input(name, template)\n    _TEMPLATE_REGISTRY[name] = template\n\n\ndef deregister_template(name: str) -> None:\n    \"\"\"Remove a named prompt template if it is registered.\"\"\"\n    _validate_template_input(name)\n    _TEMPLATE_REGISTRY.pop(name, None)\n\n\ndef clear_templates() -> None:\n    \"\"\"Remove all registered prompt templates.\"\"\"\n    _TEMPLATE_REGISTRY.clear()\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/src/llm/prompt/templates/__init__.py#L1-L32","documentation":"_validate_template_input also checks content: when a template value is provided (register_template), it must be a non-empty, non-whitespace string. register_template passes the template through this guard, so blank or non-string bodies are rejected.","triggerScenarios":"register_template('greeting', ''), register_template('greeting', '   '), register_template('greeting', None) (template=None is treated as 'not provided' by the validator, but register requires a real template), or passing a bytes/Path object instead of str.","commonSituations":"Template loaded from a file that failed to read (empty string); YAML/JSON config where the template key is missing so content is None; passing a pathlib.Path rather than reading it to text.","solutions":["Pass the actual template text as a non-empty string","Read the template file first: register_template(name, Path(p).read_text())","Validate content length before registering; check the loader that returned empty content"],"exampleFix":"// before\nregister_template('greeting', open(tpl_path).read() if tpl_path else '')\n// after\ncontent = Path(tpl_path).read_text()\nif not content.strip():\n    raise ValueError(f'template file {tpl_path} is empty')\nregister_template('greeting', content)","handlingStrategy":"validation","validationCode":"content = Path(tpl_path).read_text() if tpl_path else ''\nif not content.strip():\n    raise ValueError(f'template content for {name} is empty')","typeGuard":"def is_valid_template_body(v: object) -> bool:\n    return isinstance(v, str) and bool(v.strip())","tryCatchPattern":"try:\n    register_template(name, tpl)\nexcept ValueError as e:\n    if 'content must be a non-empty string' in str(e):\n        logger.error('empty/invalid template body for %r', name)\n        raise","preventionTips":["Check template file reads: a missing file read should error, not yield ''","Read Path objects with read_text() instead of passing the Path itself","Validate template content in config loading, before it reaches the registry"],"tags":["value-error","validation","registry","template"],"backgroundTag":"empty-required-field","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}