{"record":{"id":"c4953fb43cf8e407","repo":"FoundationAgents/MetaGPT","slug":"the-invoice-format-is-not-zip-pdf-png-or-jpg","errorCode":null,"errorMessage":"The invoice format is not zip, pdf, png, or jpg","messagePattern":"The invoice format is not zip, pdf, png, or jpg","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"metagpt/actions/invoice_ocr.py","lineNumber":58,"sourceCode":"    name: str = \"InvoiceOCR\"\n    i_context: Optional[str] = None\n\n    @staticmethod\n    async def _check_file_type(file_path: Path) -> str:\n        \"\"\"Check the file type of the given filename.\n\n        Args:\n            file_path: The path of the file.\n\n        Returns:\n            The file type based on FileExtensionType enum.\n\n        Raises:\n            Exception: If the file format is not zip, pdf, png, or jpg.\n        \"\"\"\n        ext = file_path.suffix\n        if ext not in [\".zip\", \".pdf\", \".png\", \".jpg\"]:\n            raise Exception(\"The invoice format is not zip, pdf, png, or jpg\")\n\n        return ext\n\n    @staticmethod\n    async def _unzip(file_path: Path) -> Path:\n        \"\"\"Unzip a file and return the path to the unzipped directory.\n\n        Args:\n            file_path: The path to the zip file.\n\n        Returns:\n            The path to the unzipped directory.\n        \"\"\"\n        file_directory = file_path.parent / \"unzip_invoices\" / datetime.now().strftime(\"%Y%m%d%H%M%S\")\n        with zipfile.ZipFile(file_path, \"r\") as zip_ref:\n            for zip_info in zip_ref.infolist():\n                # Use CP437 to encode the file name, and then use GBK decoding to prevent Chinese garbled code\n                relative_name = Path(zip_info.filename.encode(\"cp437\").decode(\"gbk\"))","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/actions/invoice_ocr.py#L40-L76","documentation":"InvoiceOCR (metagpt/actions/invoice_ocr.py) only processes invoices packaged as .zip, .pdf, .png, or .jpg. _get_file_type inspects the Path suffix and raises a bare Exception when the extension is not in that list, so files like .jpeg, .webp, .tiff, or extension-less paths are rejected before OCR begins.","triggerScenarios":"Calling InvoiceOCR's file-type step with Path('invoice.jpeg'), Path('scan.webp'), or a file with no suffix. Note the check is case-sensitive on the suffix, so '.PDF' also fails on case-sensitive comparisons depending on how suffix is produced ('.PDF' != '.pdf').","commonSituations":"Scanners exporting .jpeg or .tif; cameras producing .heic; uppercase extensions from Windows; passing a directory or a URL string instead of a local Path.","solutions":["Convert the invoice to PDF or PNG/JPG before running InvoiceOCR.","Rename/normalize the extension: lowercase the suffix and map '.jpeg' to '.jpg' if the bytes really are JPEG.","For .jpeg/.webp, transcode with PIL/Pillow to png first."],"exampleFix":"# before\nawait ocr_action.run(Path('invoice.jpeg'))  # Exception\n\n# after\np = Path('invoice.jpeg')\nif p.suffix.lower() == '.jpeg':\n    p = p.with_suffix('.jpg')\nawait ocr_action.run(p)","handlingStrategy":"validation","validationCode":"SUPPORTED = {'.zip', '.pdf', '.png', '.jpg'}\nif p.suffix.lower() not in SUPPORTED:\n    p = convert_to_pdf_or_png(p)  # your transcode step\nawait run_invoice_ocr(p)","typeGuard":"def is_supported_invoice(path: Path) -> bool:\n    return path.suffix.lower() in {'.zip', '.pdf', '.png', '.jpg'}","tryCatchPattern":null,"preventionTips":["Lowercase extensions before validation.","Convert .jpeg/.webp/.tiff scans to png or pdf upstream.","Reject unsupported uploads at the API boundary with a clear message."],"tags":["ocr","invoice","file-format","validation"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}