FoundationAgents/MetaGPT · error · Exception

The invoice format is not zip, pdf, png, or jpg

Error message

The invoice format is not zip, pdf, png, or jpg

What it means

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.

Source

Thrown at metagpt/actions/invoice_ocr.py:58

    name: str = "InvoiceOCR"
    i_context: Optional[str] = None

    @staticmethod
    async def _check_file_type(file_path: Path) -> str:
        """Check the file type of the given filename.

        Args:
            file_path: The path of the file.

        Returns:
            The file type based on FileExtensionType enum.

        Raises:
            Exception: If the file format is not zip, pdf, png, or jpg.
        """
        ext = file_path.suffix
        if ext not in [".zip", ".pdf", ".png", ".jpg"]:
            raise Exception("The invoice format is not zip, pdf, png, or jpg")

        return ext

    @staticmethod
    async def _unzip(file_path: Path) -> Path:
        """Unzip a file and return the path to the unzipped directory.

        Args:
            file_path: The path to the zip file.

        Returns:
            The path to the unzipped directory.
        """
        file_directory = file_path.parent / "unzip_invoices" / datetime.now().strftime("%Y%m%d%H%M%S")
        with zipfile.ZipFile(file_path, "r") as zip_ref:
            for zip_info in zip_ref.infolist():
                # Use CP437 to encode the file name, and then use GBK decoding to prevent Chinese garbled code
                relative_name = Path(zip_info.filename.encode("cp437").decode("gbk"))

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Convert the invoice to PDF or PNG/JPG before running InvoiceOCR.
  2. Rename/normalize the extension: lowercase the suffix and map '.jpeg' to '.jpg' if the bytes really are JPEG.
  3. For .jpeg/.webp, transcode with PIL/Pillow to png first.

Example fix

# before
await ocr_action.run(Path('invoice.jpeg'))  # Exception

# after
p = Path('invoice.jpeg')
if p.suffix.lower() == '.jpeg':
    p = p.with_suffix('.jpg')
await ocr_action.run(p)
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {'.zip', '.pdf', '.png', '.jpg'}
if p.suffix.lower() not in SUPPORTED:
    p = convert_to_pdf_or_png(p)  # your transcode step
await run_invoice_ocr(p)

Type guard

def is_supported_invoice(path: Path) -> bool:
    return path.suffix.lower() in {'.zip', '.pdf', '.png', '.jpg'}

Prevention

When it happens

Trigger: 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').

Common situations: Scanners exporting .jpeg or .tif; cameras producing .heic; uppercase extensions from Windows; passing a directory or a URL string instead of a local Path.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/c4953fb43cf8e407. Report an issue: GitHub.