pypa/pip · error · PylockValidationError

Unexpected type (expected )

Error message

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

What it means

Raised by _get in pylock.py:108-116 while reading a TOML key for a pylock dataclass. It fires when a present value is not the expected type, and also when expected_type is int but the value is a bool (TOML keeps bool and int distinct, even though bool subclasses int in Python). Surfaces as PylockValidationError with context set to the offending key.

Solutions

  1. Use the correct TOML scalar: unquoted integers, quoted strings, true/false booleans, native datetime.
  2. Never pass a bool where an int is expected (e.g. size).

Example fix

# before
[[packages.sdist]]
size = "12345"
# after
[[packages.sdist]]
size = 12345
Defensive patterns

Strategy: validation

Validate before calling

def toml_scalar_ok(key: str, value, expected_type: type) -> bool:
    if isinstance(value, expected_type) and not (expected_type is int and isinstance(value, bool)):
        return True
    return False

Try / catch

from packaging.pylock import Pylock, PylockValidationError

try:
    lock = Pylock.from_dict(toml_dict)
except PylockValidationError as e:
    # e.context names the offending key
    ...

Prevention

When it happens

Trigger: In a pylock TOML: size = "12345" (str where int expected), size = true (bool where int expected), index = 5 (int where str expected), upload-time = "2024-01-01 00:00:00" (str where datetime expected).

Common situations: Hand-editing pylock.toml with quoted numbers; a TOML emitter that quotes everything as strings; using true/false where an integer size is required.

Related errors


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

Appendix: source

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


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) or (
        # Special case: bool is a subclass of int, but TOML distinguishes the two
        expected_type is int and isinstance(value, bool)
    ):
        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 f399c37189)