{"record":{"id":"d391057a050e9586","repo":"twentyhq/twenty","slug":"input-dir-is-not-a-directory","errorCode":null,"errorMessage":"{input_dir} is not a directory","messagePattern":"(.+?) is not a directory","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/twenty-server/src/engine/core-modules/code-interpreter/sandbox-scripts/docx/pack.py","lineNumber":60,"sourceCode":"        sys.exit(f\"Error: {e}\")\n\n\ndef pack_document(input_dir, output_file, validate=False):\n    \"\"\"Pack a directory into an Office file (.docx/.pptx/.xlsx).\n\n    Args:\n        input_dir: Path to unpacked Office document directory\n        output_file: Path to output Office file\n        validate: If True, validates with soffice (default: False)\n\n    Returns:\n        bool: True if successful, False if validation failed\n    \"\"\"\n    input_dir = Path(input_dir)\n    output_file = Path(output_file)\n\n    if not input_dir.is_dir():\n        raise ValueError(f\"{input_dir} is not a directory\")\n    if output_file.suffix.lower() not in {\".docx\", \".pptx\", \".xlsx\"}:\n        raise ValueError(f\"{output_file} must be a .docx, .pptx, or .xlsx file\")\n\n    # Work in temporary directory to avoid modifying original\n    with tempfile.TemporaryDirectory() as temp_dir:\n        temp_content_dir = Path(temp_dir) / \"content\"\n        shutil.copytree(input_dir, temp_content_dir)\n\n        # Process XML files to remove pretty-printing whitespace\n        for pattern in [\"*.xml\", \"*.rels\"]:\n            for xml_file in temp_content_dir.rglob(pattern):\n                condense_xml(xml_file)\n\n        # Create final Office file as zip archive\n        output_file.parent.mkdir(parents=True, exist_ok=True)\n        with zipfile.ZipFile(output_file, \"w\", zipfile.ZIP_DEFLATED) as zf:\n            for f in temp_content_dir.rglob(\"*\"):\n                if f.is_file():","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-server/src/engine/core-modules/code-interpreter/sandbox-scripts/docx/pack.py#L42-L78","documentation":"Raised by pack.py's pack function, which re-zips an unpacked Office document directory back into a .docx/.pptx/.xlsx file. It guards input_dir.is_dir() before copying the tree into a temp working directory. The function expects the on-disk layout produced by the matching unpack.py (the OOXML directory structure with [Content_Types].xml, _rels/, word|ppt|xl/).","triggerScenarios":"Calling pack() with a path that does not exist, points to a regular file (e.g. passing a .docx instead of its unpacked directory), or points to a directory that was never created because a prior unpack step failed silently.","commonSituations":"Code-interpreter sandbox pipeline where an LLM-generated script calls unpack then pack but the unpack step crashed, leaving no directory; or a path-joining bug (e.g. packing the output file path rather than the directory). Also when the working directory assumption differs between the caller and pack.py.","solutions":["Verify the path exists and is a directory before calling pack: `Path(input_dir).is_dir()`.","Ensure the preceding unpack step succeeded and returned the directory it created.","Pass an absolute path to avoid cwd-relative ambiguity inside the sandbox.","Confirm the directory contains [Content_Types].xml — if not, it is not a valid unpacked OOXML tree."],"exampleFix":"# before\npack('/tmp/out.docx', '/tmp/result.docx')   # passing a file, not the unpacked dir\n# after\npack('/tmp/unpacked_out.docx', '/tmp/result.docx')   # the directory unpack() produced","handlingStrategy":"type-guard","validationCode":"from pathlib import Path\n\ndef safe_pack(input_dir, output_file):\n    p = Path(input_dir)\n    if not p.exists():\n        raise FileNotFoundError(f'Input path does not exist: {input_dir}')\n    if not p.is_dir():\n        raise NotADirectoryError(f'Input path is not a directory: {input_dir}')\n    if not (p / '[Content_Types].xml').exists():\n        raise ValueError(f'Not a valid OOXML tree (missing [Content_Types].xml): {input_dir}')\n    return pack(input_dir, output_file)","typeGuard":"from pathlib import Path\n\ndef is_unpacked_ooxml_dir(path: str) -> bool:\n    p = Path(path)\n    return p.is_dir() and (p / '[Content_Types].xml').exists()","tryCatchPattern":"from pathlib import Path\ntry:\n    pack(input_dir, output_file)\nexcept ValueError as e:\n    if 'is not a directory' in str(e):\n        # recover: maybe caller passed the .docx; try unpacking first\n        if Path(input_dir).is_file():\n            unpacked = unpack(input_dir, tempfile.mkdtemp())\n            pack(unpacked, output_file)\n        else:\n            raise\n    else:\n        raise","preventionTips":["Always pair pack() with the matching unpack() output; never derive the input path from a filename.","Check is_dir() and the presence of [Content_Types].xml before packing.","Pass absolute paths to avoid cwd ambiguity inside sandboxes."],"tags":["python","office-doc","code-interpreter","filesystem","validation"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}