pypa/pip · error · InstallationError

Unknown scheme key used in {wheel_path}: {scheme_key} (for f

Error message

Unknown scheme key used in {wheel_path}: {scheme_key} (for file {record_path!r}). .data directory contents should be in subdirectories named with a valid scheme key ({valid_scheme_keys})

What it means

Raised as InstallationError at wheel.py:526-536 when a file under the *.data directory uses a scheme key that is not one of the recognized SCHEME_KEYS. The code builds scheme_paths from the current Scheme and raises KeyError when looking up scheme_paths[scheme_key], then formats the list of valid keys into the message.

Source

Thrown at src/pip/_internal/operations/install/wheel.py:536

                _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2)
            except ValueError:
                message = (
                    f"Unexpected file in {wheel_path}: {record_path!r}. .data directory"
                    " contents should be named like: '<scheme key>/<path>'."
                )
                raise InstallationError(message)

            try:
                scheme_path = scheme_paths[scheme_key]
            except KeyError:
                valid_scheme_keys = ", ".join(sorted(scheme_paths))
                message = (
                    f"Unknown scheme key used in {wheel_path}: {scheme_key} "
                    f"(for file {record_path!r}). .data directory contents "
                    f"should be in subdirectories named with a valid scheme "
                    f"key ({valid_scheme_keys})"
                )
                raise InstallationError(message)

            dest_path = os.path.join(scheme_path, dest_subpath)
            assert_no_path_traversal(scheme_path, dest_path)
            return ZipBackedFile(record_path, dest_path, zip_file)

        return make_data_scheme_file

    def is_data_scheme_path(path: RecordPath) -> bool:
        return path.split("/", 1)[0].endswith(".data")

    paths = cast(list[RecordPath], wheel_zip.namelist())
    file_paths = filterfalse(is_dir_path, paths)
    root_scheme_paths, data_scheme_paths = partition(is_data_scheme_path, file_paths)

    make_root_scheme_file = root_scheme_file_maker(wheel_zip, lib_dir)
    files: Iterator[File] = map(make_root_scheme_file, root_scheme_paths)

    def is_script_scheme_path(path: RecordPath) -> bool:

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Inspect the *.data/ subdirectories of the wheel and compare against the valid scheme keys listed in the error message (purelib, platlib, headers, scripts, data).
  2. Move files into the correct scheme-key subdirectory and rebuild the wheel.
  3. Use a PEP 517-compliant build backend to regenerate the wheel.
  4. Pin to a version of the package whose wheel uses valid scheme keys.

Example fix

# before
mypkg-1.0.data/libextra/foo.so

# after
mypkg-1.0.data/platlib/foo.so
Defensive patterns

Strategy: validation

Validate before calling

from pip._internal.models.scheme import SCHEME_KEYS
import zipfile

def validate_wheel_scheme_keys(whl):
    with zipfile.ZipFile(whl) as z:
        for n in z.namelist():
            if "/" in n and n.split("/", 1)[0].endswith(".data"):
                key = n.split("/", 2)[1]
                if key not in SCHEME_KEYS:
                    raise ValueError(f"unknown scheme key '{key}' in {n}; valid: {sorted(SCHEME_KEYS)}")

Type guard

from pip._internal.models.scheme import SCHEME_KEYS
def is_valid_scheme_key(record_path: str) -> bool:
    parts = record_path.split("/", 2)
    return len(parts) >= 2 and parts[1] in SCHEME_KEYS

Prevention

When it happens

Trigger: A wheel's *.data directory has a subdirectory name other than the valid scheme keys. E.g. 'mypkg-1.0.data/libfoo/foo.so' where 'libfoo' is not a valid scheme key (valid: purelib, platlib, headers, scripts, data).

Common situations: Non-standard build backends or wheels produced by tools that invent custom scheme subdirectories. Manually crafted wheels. Wheels targeting a different platform's scheme layout.

Related errors


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