deepfakes/faceswap · error · ValueError

Invalid header found in png: {filename}

Error message

Invalid header found in png: {filename}

What it means

Raised when the first 8 bytes of a file do not match the PNG magic signature (\x89PNG\r\x1a\n) in faceswap's lightweight PNG dimension reader. The library assumes files with a .png extension (or detected as png) start with a valid PNG header; a mismatch means the file is corrupt, truncated, or not actually a PNG.

Source

Thrown at lib/image.py:279

    """
    retval = {}
    if os.path.splitext(filename)[-1].lower() != ".png":
        # Get the dimensions directly from the image for non-png
        logger.trace(  # type:ignore[attr-defined]
            "Non png found. Loading file for dimensions: '%s'",
            filename)
        img = cv2.imread(filename)
        assert img is not None
        retval["height"], retval["width"] = img.shape[:2]
        return retval
    with open(filename, "rb") as in_file:
        try:
            chunk = in_file.read(8)
        except PermissionError as exc:
            raise PermissionError(f"PermissionError while reading: {filename}") from exc

        if chunk != b"\x89PNG\r\n\x1a\n":
            raise ValueError(f"Invalid header found in png: {filename}")

        while True:
            chunk = in_file.read(8)
            length, field = struct.unpack(">I4s", chunk)
            logger.trace(  # type:ignore[attr-defined]
                "Read chunk: (chunk: %s, length: %s, field: %s",
                chunk, length, field)
            if not chunk or field == b"IDAT":
                break
            if field == b"IHDR":
                # Get dimensions
                chunk = in_file.read(8)
                retval["width"], retval["height"] = struct.unpack(">II", chunk)
                length -= 8
            elif field == b"iTXt":
                keyword, value = in_file.read(length).split(b"\0", 1)
                if keyword == b"faceswap":
                    retval["itxt"] = literal_eval(value[4:].decode("utf-8", errors="replace"))

View on GitHub (pinned to f530cb7508)

Solutions

  1. Verify and re-convert the offending file: open it in an image editor or with PIL/cv2 and re-save as real PNG (or correct its extension to the actual format).
  2. Remove corrupt files from the input folder; validate the dataset with a magic-byte check before running faceswap.
  3. Re-download/re-transfer the file if it was truncated.

Example fix

import struct

# before: assume every .png is a png
# after: validate magic bytes before handing folder to faceswap
with open(path, 'rb') as f:
    if f.read(8) != b'\x89PNG\r\n\x1a\n':
        print('not a real png, skipping:', path)
Defensive patterns

Strategy: validation

Validate before calling

PNG_MAGIC = b'\x89PNG\r\n\x1a\n'

def is_png(path: str) -> bool:
    with open(path, 'rb') as f:
        return f.read(8) == PNG_MAGIC

Try / catch

try:
    meta = read_image_meta(path)
except ValueError as err:
    if 'Invalid header' in str(err):
        quarantine.append(path)  # move aside and continue
    else:
        raise

Prevention

When it happens

Trigger: A file with a .png extension whose content is JPEG/WebP/other format, a truncated or zero-byte download, or a file that was renamed to .png without conversion. Hit when faceswap enumerates a folder and probes each file for PNG dimensions.

Common situations: Datasets scraped from the web with wrong extensions, images partially downloaded or corrupted by transfer, files double-compressed or re-saved by tools that mangled headers, mixed-format folders.

Related errors


AI-assisted analysis of deepfakes/faceswap@f530cb7508 (2026-08-15). Data as JSON: /api/errors/bc5feffbec826577. Report an issue: GitHub.