ATH-MaaS/Pixelle-Video · error · ValueError
Invalid response format: missing 'narrations' key
Error message
Invalid response format: missing 'narrations' key
What it means
generate_narrations_from_topic parses the LLM response as JSON and requires a top-level "narrations" key; ValueError is raised when the model's output doesn't match the expected schema. This guards against LLMs returning prose, wrapped markdown, or differently named keys.
Source
Thrown at pixelle_video/utils/content_generators.py:138
topic=topic,
n_storyboard=n_scenes,
min_words=min_words,
max_words=max_words
)
response = await llm_service(
prompt=prompt,
temperature=0.8,
max_tokens=2000
)
logger.debug(f"LLM response: {response[:200]}...")
# Parse JSON
result = _parse_json(response)
if "narrations" not in result:
raise ValueError("Invalid response format: missing 'narrations' key")
narrations = result["narrations"]
# Validate count
if len(narrations) > n_scenes:
logger.warning(f"Got {len(narrations)} narrations, taking first {n_scenes}")
narrations = narrations[:n_scenes]
elif len(narrations) < n_scenes:
raise ValueError(f"Expected {n_scenes} narrations, got only {len(narrations)}")
logger.info(f"Generated {len(narrations)} narrations successfully")
return narrations
async def generate_narrations_from_content(
llm_service,
content: str,
n_scenes: int = 5,View on GitHub (pinned to 848b054e4f)
Solutions
- Check the logged 'LLM response' debug line to see the actual shape returned
- Strengthen the prompt to demand exactly {"narrations": [...]} with n_scenes items
- Lower temperature / use a model that reliably follows JSON instructions
- Add few-shot examples of the expected JSON in the prompt
Example fix
// model returned {"scenes": ["a","b"]}
// before
narrations = result["scenes"]
// after (fix the prompt, or normalize)
if "narrations" not in result and "scenes" in result:
result = {"narrations": result["scenes"]} Defensive patterns
Strategy: validation
Validate before calling
def is_valid_narration_result(result, n_scenes: int) -> bool:
return (
isinstance(result, dict)
and isinstance(result.get('narrations'), list)
and len(result['narrations']) == n_scenes
and all(isinstance(n, str) and n.strip() for n in result['narrations'])
) Type guard
def has_narrations(x) -> bool:
return isinstance(x, dict) and isinstance(x.get('narrations'), list) Try / catch
try:
narrations = await generate_narrations_from_topic(topic, n_scenes=n)
except ValueError as e:
if 'missing' in str(e):
narrations = await generate_narrations_from_topic(topic, n_scenes=n, retry_with_stricter_schema=True)
else:
raise Prevention
- Use the model's JSON/structured-output mode when available
- Include an exact-schema example in the prompt
- Log raw LLM responses for post-mortem on schema drift
When it happens
Trigger: Calling generate_narration/generate_content which routes here when the LLM reply, after _parse_json, is a dict without "narrations" — e.g. the model returned {"scenes": [...]}, a bare array, or explanation text instead of the requested JSON schema.
Common situations: Weak/non-instruct models ignoring the JSON schema; temperature too high producing prose; prompt template edited so the schema instruction is lost; model wrapping JSON in markdown fences that _parse_json strips only partially.
Related errors
- Invalid response format: missing 'image_prompts'
- Invalid response format: missing 'video_prompts'
- Failed to parse LLM response as {response_type.__name__}: {c
- Expected {n_scenes} narrations, got only {len(narrations)}
- str(e)
AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30).
Data as JSON: /api/errors/cdf4fa1b1213a899.
Report an issue: GitHub.