pypa/pip · error · PylockValidationError

Unexpected type {type(value).__name__} (expected {expected_t

Error message

Unexpected type {type(value).__name__} (expected {expected_type.__name__})

What it means

Raised as PylockValidationError by _get in packaging.pylock when a TOML value for a key exists but is not the expected scalar type. pylock (PEP 771 lockfile) strictly type-checks every field; for example 'size' must be int, 'name' must be str. The context field records the offending key path.

Source

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

    if isinstance(value, Sequence) and key == "environments":
        return [str(v) for v in value]
    return value


def _toml_dict_factory(data: list[tuple[str, Any]]) -> dict[str, Any]:
    return {
        _toml_key(key): _toml_value(key, value)
        for key, value in data
        if value is not None
    }


def _get(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T | None:
    """Get a value from the dictionary and verify it's the expected type."""
    if (value := d.get(key)) is None:
        return None
    if not isinstance(value, expected_type):
        raise PylockValidationError(
            f"Unexpected type {type(value).__name__} "
            f"(expected {expected_type.__name__})",
            context=key,
        )
    return value


def _get_required(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T:
    """Get a required value from the dictionary and verify it's the expected type."""
    if (value := _get(d, expected_type, key)) is None:
        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."""

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Open the pylock.toml and correct the value to the expected type shown in the error.
  2. Regenerate the lockfile with a compliant resolver rather than editing by hand.
  3. Pre-validate the TOML against the pylock JSON schema before loading.
  4. Catch PylockValidationError and report the offending key (e.context) to the user.

Example fix

# before
size = \"1024\"
# after
size = 1024
Defensive patterns

Strategy: type-guard

Validate before calling

def check_types(d, spec):
    # spec: {key: expected_type}
    for k, t in spec.items():
        v = d.get(k)
        if v is not None and not isinstance(v, t):
            raise TypeError(f'{k}: expected {t.__name__}, got {type(v).__name__}')

Type guard

def is_correct_type(value, expected_type) -> bool:
    return value is None or isinstance(value, expected_type)

Try / catch

from packaging.pylock import PylockValidationError
try:
    PylockFile.from_dict(data)
except PylockValidationError as e:
    log.error('pylock field %s: %s', e.context, e.message)

Prevention

When it happens

Trigger: Loading a pylock.toml where size = \"12345\" (string instead of int), or upload-time = 12345 (int instead of ISO str), or name = 42. Calling PylockFile.from_dict on a hand-built dict with wrong types.

Common situations: Hand-edited lockfiles; tooling that emits numbers as strings; schema drift between pylock versions; YAML->TOML converters that lose typing.

Related errors


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