pypa/pip · error · ELFInvalid

unable to parse identification

Error message

unable to parse identification

What it means

Raised by the vendored `packaging._elffile.ELFFile` constructor when `struct.unpack` fails reading the initial 16-byte `e_ident` header. It means the file object yielded fewer than 16 bytes (truncated, empty, or not seekable correctly), so the parser cannot even begin. The original `struct.error` is chained as the cause.

Source

Thrown at src/pip/_vendor/packaging/_elffile.py:51

    I386 = 3
    S390 = 22
    Arm = 40
    X8664 = 62
    AArc64 = 183


class ELFFile:
    """
    Representation of an ELF executable.
    """

    def __init__(self, f: IO[bytes]) -> None:
        self._f = f

        try:
            ident = self._read("16B")
        except struct.error as e:
            raise ELFInvalid("unable to parse identification") from e
        magic = bytes(ident[:4])
        if magic != b"\x7fELF":
            raise ELFInvalid(f"invalid magic: {magic!r}")

        self.capacity = ident[4]  # Format for program header (bitness).
        self.encoding = ident[5]  # Data structure encoding (endianness).

        try:
            # e_fmt: Format for program header.
            # p_fmt: Format for section header.
            # p_idx: Indexes to find p_type, p_offset, and p_filesz.
            e_fmt, self._p_fmt, self._p_idx = {
                (1, 1): ("<HHIIIIIHHH", "<IIIIIIII", (0, 1, 4)),  # 32-bit LSB.
                (1, 2): (">HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)),  # 32-bit MSB.
                (2, 1): ("<HHIQQQIHHH", "<IIQQQQQQ", (0, 2, 5)),  # 64-bit LSB.
                (2, 2): (">HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)),  # 64-bit MSB.
            }[(self.capacity, self.encoding)]
        except KeyError as e:

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Verify the file size is at least 16 bytes before constructing ELFFile: `if os.path.getsize(path) < 16: skip`
  2. Guard construction with try/except ELFInvalid and skip the file
  3. Confirm you actually intend to parse an ELF (Linux/Android binary), not Mach-O or PE

Example fix

// before
elf = ELFFile(open(path, 'rb'))
// after
import os
if os.path.getsize(path) < 64:
    raise ValueError(f'{path} too small to be ELF')
try:
    elf = ELFFile(open(path, 'rb'))
except ELFInvalid:
    raise ValueError(f'{path} is not a valid ELF file')
Defensive patterns

Strategy: try-catch

Validate before calling

import os
from packaging._elffile import ELFFile, ELFInvalid

def open_elf(path: str):
    if os.path.getsize(path) < 16:
        raise ValueError(f'{path} too small to be ELF (<16 bytes)')
    return ELFFile(open(path, 'rb'))

Type guard

def looks_like_elf(path: str) -> bool:
    import os
    return os.path.getsize(path) >= 16 and open(path,'rb').read(4) == b'\x7fELF'

Try / catch

from packaging._elffile import ELFFile, ELFInvalid
try:
    elf = ELFFile(f)
except ELFInvalid as e:
    log.warning('skipping %s: %s', path, e)
    continue

Prevention

When it happens

Trigger: Instantiating `ELFFile(f)` where `f` is empty, shorter than 16 bytes, a text-mode file, or a stream already at EOF. Also when the wrong file object is passed (e.g. a directory handle) or the path points to a 0-byte file.

Common situations: A build tool or manylinux/pip audit reading a `.so`/wheel payload that was incompletely downloaded; passing a non-ELF artifact (a shell script with no shebang magic, a Mach-O binary, a PE `.exe`) to `ELFFile`; reading from a pipe that closed early.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/77c431fb89e453d2.json. Report an issue: GitHub.