opendatalab/MinerU · error · ValueError

Invalid PPTX package: file is not a ZIP archive.

Error message

Invalid PPTX package: file is not a ZIP archive.

What it means

The PPTX normalizer opens the input with ZipFile; a zipfile.BadZipFile escapes the reader and is re-raised as ValueError('Invalid PPTX package: file is not a ZIP archive.'). Every OOXML file (.pptx) is a ZIP, so this means the bytes are not a .pptx at all.

Source

Thrown at mineru/model/pptx/package_normalizer.py:121

            for info in source.infolist():
                member_data = _read_member_best_effort(source, info)
                if member_data is None:
                    skipped_members.add(info.filename)
                    changed = True
                    continue
                loaded_members.append((info, member_data))

            for info, member_data in loaded_members:
                normalized_data = _normalize_member_xml(
                    info.filename,
                    member_data,
                    skipped_members,
                )
                if normalized_data != member_data:
                    changed = True
                rewritten_members.append((info, normalized_data))
    except BadZipFile as exc:
        raise ValueError("Invalid PPTX package: file is not a ZIP archive.") from exc

    if not changed:
        return file_bytes

    return _write_package(rewritten_members)


def _read_member_best_effort(source: ZipFile, info: ZipInfo) -> bytes | None:
    """读取 ZIP 成员;损坏的媒体资源可跳过,关键 XML/关系文件仍保持失败。"""
    try:
        return source.read(info.filename)
    except BadZipFile as exc:
        if _is_skippable_corrupt_member(info.filename):
            logger.warning(
                f"Skipping corrupt non-critical PPTX media member {info.filename}: {exc}"
            )
            return None
        raise

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Verify the first bytes are 'PK\\x03\\x04' before parsing.
  2. Re-obtain the file (re-download, re-export) if truncated.
  3. If it starts with D0 CF 11 E0, it is either legacy .ppt (convert it) or an encrypted package (decrypt then parse).

Example fix

# before
data = open(f'{name}.pptx','rb').read()  # actually legacy bytes
normalize_pptx_package(data)

# after
if not data.startswith(b'PK\\x03\\x04'):
    raise SystemExit('not a pptx zip; convert first')
normalize_pptx_package(data)
Defensive patterns

Strategy: validation

Validate before calling

def is_zip_package(data: bytes) -> bool:
    return data[:4] == b'PK\\x03\\x04'

Try / catch

try:
    normalize_pptx_package(data)
except ValueError as e:
    if 'not a ZIP archive' in str(e):
        # decide: legacy OLE2 -> convert; truncated -> re-fetch
        raise
    raise

Prevention

When it happens

Trigger: Passing a legacy .ppt (OLE2), an RTF/HTML file renamed to .pptx, a password-protected/encrypted OOXML package (which is stored as an OLE container), or a truncated download.

Common situations: Upload endpoints trusting the client-supplied extension, partially downloaded or interrupted transfers, files exported as strict OOXML but corrupted by transfer encoding.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/86cdabf25e312305. Report an issue: GitHub.