pypa/pip · error · PylockValidationError

Unexpected type {type(item).__name__} (expected {expected_it

Error message

Unexpected type {type(item).__name__} (expected {expected_item_type.__name__})

What it means

Raised as PylockValidationError by _get_sequence in packaging.pylock when a sequence field's elements are not all of the expected item type. The context is set to '{key}[{i}]' so the exact offending index is reported. For example dependencies must be a list of Mapping, wheels a list of Mapping; a scalar element triggers this.

Source

Thrown at src/pip/_vendor/packaging/pylock.py:132

        raise _PylockRequiredKeyError(key)
    return value


def _get_sequence(
    d: Mapping[str, Any], expected_item_type: type[_T], key: str
) -> Sequence[_T] | None:
    """Get a list value from the dictionary and verify it's the expected items type."""
    if (value := _get(d, Sequence, key)) is None:  # type: ignore[type-abstract]
        return None
    if isinstance(value, (str, bytes)):
        # special case: str and bytes are Sequences, but we want to reject it
        raise PylockValidationError(
            f"Unexpected type {type(value).__name__} (expected Sequence)",
            context=key,
        )
    for i, item in enumerate(value):
        if not isinstance(item, expected_item_type):
            raise PylockValidationError(
                f"Unexpected type {type(item).__name__} "
                f"(expected {expected_item_type.__name__})",
                context=f"{key}[{i}]",
            )
    return value


def _get_as(
    d: Mapping[str, Any],
    expected_type: type[_T],
    target_type: Callable[[_T], _T2],
    key: str,
) -> _T2 | None:
    """Get a value from the dictionary, verify it's the expected type,
    and convert to the target type.

    This assumes the target_type constructor accepts the value.
    """

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Make each list element an inline table of the right shape, e.g. dependencies = [{ name = \"foo\", ... }].
  2. Regenerate the lockfile with a compliant resolver so element shapes are correct.
  3. Validate element schemas before calling from_dict.
  4. Inspect e.context to find the failing key[index].

Example fix

# before
dependencies = [\"requests\"]
# after
dependencies = [{ name = \"requests\", version = \"2.31.0\" }]
Defensive patterns

Strategy: type-guard

Validate before calling

def all_items_match(seq, item_type) -> bool:
    return all(isinstance(x, item_type) for x in seq)

Type guard

from typing import Any, Sequence as Seq

def is_homogeneous_sequence(value: Seq[Any], item_type) -> bool:
    return all(isinstance(x, item_type) for x in value)

Try / catch

try:
    PylockFile.from_dict(data)
except PylockValidationError as e:
    # e.context like 'wheels[2]' or 'dependencies[0]'
    fix_element(e.context)

Prevention

When it happens

Trigger: dependencies = [\"foo\"] where the expected item type is Mapping (it should be a list of inline tables); wheels = [\"a.whl\", 42]; attestation-identities containing a string instead of a table.

Common situations: Authoring a pylock by hand and putting scalars where tables belong; converting from requirements.txt where each line is a string rather than a dependency object.

Related errors


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