{"record":{"id":"f35212d9b0694dc4","repo":"ATH-MaaS/Pixelle-Video","slug":"expected-n-scenes-narrations-got-only-len-narr","errorCode":null,"errorMessage":"Expected {n_scenes} narrations, got only {len(narrations)}","messagePattern":"Expected (.+?) narrations, got only (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pixelle_video/utils/content_generators.py","lineNumber":147,"sourceCode":"        max_tokens=2000\n    )\n    \n    logger.debug(f\"LLM response: {response[:200]}...\")\n    \n    # Parse JSON\n    result = _parse_json(response)\n    \n    if \"narrations\" not in result:\n        raise ValueError(\"Invalid response format: missing 'narrations' key\")\n    \n    narrations = result[\"narrations\"]\n    \n    # Validate count\n    if len(narrations) > n_scenes:\n        logger.warning(f\"Got {len(narrations)} narrations, taking first {n_scenes}\")\n        narrations = narrations[:n_scenes]\n    elif len(narrations) < n_scenes:\n        raise ValueError(f\"Expected {n_scenes} narrations, got only {len(narrations)}\")\n    \n    logger.info(f\"Generated {len(narrations)} narrations successfully\")\n    return narrations\n\n\nasync def generate_narrations_from_content(\n    llm_service,\n    content: str,\n    n_scenes: int = 5,\n    min_words: int = 5,\n    max_words: int = 20\n) -> List[str]:\n    \"\"\"\n    Generate narrations from user-provided content using LLM\n    \n    Args:\n        llm_service: LLM service instance\n        content: User-provided content","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/utils/content_generators.py#L129-L165","documentation":"generate_narrations_from_topic validates narration count against n_scenes: extra narrations are truncated with a warning, but fewer than requested raises ValueError. One narration per scene is required downstream, so a short LLM response is treated as a hard failure rather than silently padded.","triggerScenarios":"The LLM returns a valid {\"narrations\": [...]} array with len < n_scenes — the model merged scenes, stopped early, or hit a max-token limit mid-generation.","commonSituations":"High scene counts (long videos) exceeding the model's output token budget; the model combining adjacent scenes into one narration; responses truncated by API max_tokens settings.","solutions":["Retry the generation — LLM undercounting is often transient","Increase the model's max output tokens so all n_scenes items fit","Reduce n_scenes or split generation into batches of scenes","Add an explicit instruction: 'return exactly N narrations, one per scene'"],"exampleFix":"// before\ndesc = await generate_narration(topic, n_scenes=30)  # model returns 12\n// after\ndesc = await generate_narration(topic, n_scenes=30, max_tokens=4096)  # or batch in chunks of 10","handlingStrategy":"retry","validationCode":"def narrations_complete(result, n_scenes: int) -> bool:\n    return isinstance(result, dict) and len(result.get('narrations', [])) >= n_scenes","typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        return await generate_narrations_from_topic(topic, n_scenes=n)\n    except ValueError as e:\n        if 'got only' in str(e) and attempt < 2:\n            continue\n        raise","preventionTips":["Set max_tokens high enough for n_scenes narrations","Instruct the model: 'return exactly N items, one per scene'","Batch large scene counts into chunks under the token budget"],"tags":["llm","count-mismatch","narration","token-limit"],"backgroundTag":"llm-response-schema-mismatch","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}