{"record":{"id":"19f4ef11a514c4c8","repo":"twentyhq/twenty","slug":"found-len-errors-validation-error-s","errorCode":null,"errorMessage":"Found {len(errors)} validation error(s)","messagePattern":"Found (.+?) validation error\\(s\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/twenty-server/src/engine/core-modules/code-interpreter/sandbox-scripts/pptx/replace.py","lineNumber":241,"sourceCode":"\n    # Detect text overflow in original presentation\n    original_overflow = detect_frame_overflow(inventory)\n\n    # Load replacement data with duplicate key detection\n    with open(json_file, \"r\") as f:\n        replacements = json.load(f, object_pairs_hook=check_duplicate_keys)\n\n    # Validate replacements\n    errors = validate_replacements(inventory, replacements)\n    if errors:\n        print(\"ERROR: Invalid shapes in replacement JSON:\")\n        for error in errors:\n            print(f\"  - {error}\")\n        print(\"\\nPlease check the inventory and update your replacement JSON.\")\n        print(\n            \"You can regenerate the inventory with: python inventory.py <input.pptx> <output.json>\"\n        )\n        raise ValueError(f\"Found {len(errors)} validation error(s)\")\n\n    # Track statistics\n    shapes_processed = 0\n    shapes_cleared = 0\n    shapes_replaced = 0\n\n    # Process each slide from inventory\n    for slide_key, shapes_dict in inventory.items():\n        if not slide_key.startswith(\"slide-\"):\n            continue\n\n        slide_index = int(slide_key.split(\"-\")[1])\n\n        if slide_index >= len(prs.slides):\n            print(f\"Warning: Slide {slide_index} not found\")\n            continue\n\n        # Process each shape from inventory","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-server/src/engine/core-modules/code-interpreter/sandbox-scripts/pptx/replace.py#L223-L259","documentation":"Raised by apply_replacements in replace.py after validate_replacements returns a non-empty error list. validate_replacements checks every shape referenced in the replacement JSON against the inventory of actual text shapes on the deck; any shape_key or slide_key that does not exist, or shapes on the slide that were left without a replacement when the file intended full coverage, becomes an error. The throw halts before any slide is mutated.","triggerScenarios":"The replacement JSON references a shape name that does not exist on the named slide, references a slide key (slide-N) whose N is out of range, or — when the replacement file was meant to cover all content shapes — leaves shapes un-replaced. The detailed per-error list is printed to stdout just before the throw.","commonSituations":"An LLM edits an old replacement JSON after the deck changed (shapes renamed/reordered); a replacement file built from one deck is reused on another; typos in shape keys; a partial replacement intended for a few shapes but run in strict-full-coverage mode.","solutions":["Read the printed error list — each line names the offending slide/shape and what was expected.","Regenerate the inventory with `python inventory.py <input.pptx> <inventory.json>` and align your replacement keys to the current shape names.","If you only want to replace some shapes, ensure your replacement file's intent matches what validate_replacements expects (see its unused-shape handling).","Re-run apply_replacements once every reported shape key exists in the inventory."],"exampleFix":"# before — replacement references shape 'Subtitle' that no longer exists\npython replace.py deck.pptx bad_replacements.json out.pptx\n# after — regenerate inventory, then rebuild replacements against real shape names\npython inventory.py deck.pptx inventory.json\n# edit replacements.json to use the keys inventory.json lists, then:\npython replace.py deck.pptx replacements.json out.pptx","handlingStrategy":"validation","validationCode":"import json\nfrom inventory import build_inventory\n\ndef prevalidate_replacements(pptx_path: str, replacements_path: str) -> list[str]:\n    inventory = build_inventory(pptx_path)\n    with open(replacements_path) as f:\n        replacements = json.load(f, object_pairs_hook=check_duplicate_keys)\n    return validate_replacements(inventory, replacements)  # returns [] when clean","typeGuard":"def replacements_are_clean(inventory: dict, replacements: dict) -> bool:\n    return not validate_replacements(inventory, replacements)","tryCatchPattern":"try:\n    apply_replacements(pptx, replacements_json, output)\nexcept ValueError as e:\n    if 'validation error' in str(e):\n        # errors already printed to stdout; regenerate inventory and prompt for a fixed file\n        run_inventory(pptx, 'inventory.json')\n        raise SystemExit('Replacements did not match inventory. See errors above; inventory.json regenerated.')\n    raise","preventionTips":["Regenerate the inventory immediately before building replacements so shape names match the current deck.","Run validate_replacements as a pre-flight and refuse to proceed on any error.","Treat shape keys as opaque identifiers from the inventory — never hand-type them."],"tags":["python","pptx","code-interpreter","validation","shape-replacement"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}