pypa/pip · error · PylockValidationError
Unexpected type (expected Sequence)
Error message
Unexpected type {type(value).__name__} (expected Sequence) What it means
Raised by _get_sequence in pylock.py:133-138. Although str and bytes are technically Sequences, the pylock spec requires a TOML array, so a str/bytes value is explicitly rejected with PylockValidationError (context = key).
Solutions
- Wrap the value in square brackets to make it a TOML array.
Example fix
# before [[packages]] dependencies = "requests" # after [[packages]] dependencies = ["requests"]
Defensive patterns
Strategy: type-guard
Validate before calling
def ensure_array(key: str, value):
if isinstance(value, (str, bytes)):
raise TypeError(f"{key} must be an array, got {type(value).__name__}")
return value
Type guard
from collections.abc import Sequence
def is_real_sequence(value) -> bool:
return isinstance(value, Sequence) and not isinstance(value, (str, bytes))
Try / catch
from packaging.pylock import Pylock, PylockValidationError
try:
Pylock.from_dict(d)
except PylockValidationError as e:
...
Prevention
- Always use TOML arrays ([...]) for list-valued pylock fields.
- Reject str/bytes at your own TOML-loading boundary before handing to pylock.
When it happens
Trigger: In pylock TOML: dependencies = "requests" (string, expected array), environments = "python_version >= '3.9'" (expected array of marker strings), extras = "test" (expected array).
Common situations: Writing a scalar where the spec wants a list; forgetting square brackets around a single-element array.
Related errors
- Unexpected type (expected )
- Unexpected type (expected )
- Hash values must be strings
- Invalid pylock file
- At least one hash must be provided
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/ee86a88f9353c081.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/pylock.py:135
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."""
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,View on GitHub (pinned to f399c37189)