pypa/pip · error · PylockValidationError
Unexpected type {type(value).__name__} (expected Sequence)
Error message
Unexpected type {type(value).__name__} (expected Sequence) What it means
Raised as PylockValidationError by _get_sequence in packaging.pylock when a field that must be a list/sequence is instead a str or bytes. str and bytes are technically Sequences in Python, but pylock rejects them to prevent silent character-by-character iteration; the expected value is a real TOML array.
Source
Thrown at src/pip/_vendor/packaging/pylock.py:126
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 d7d0d0a394)
Solutions
- Wrap the value in TOML array brackets: dependencies = [\"foo\"], wheels = [\"pkg-1.0.whl\"].
- Regenerate the lockfile with a spec-compliant tool.
- Validate the TOML structure (arrays for sequence fields) before calling PylockFile.from_dict.
- Catch PylockValidationError and point the user at the key in e.context.
Example fix
# before dependencies = \"requests\" # after dependencies = [\"requests\"]
Defensive patterns
Strategy: type-guard
Validate before calling
from collections.abc import Sequence
def is_real_sequence(v) -> bool:
return isinstance(v, Sequence) and not isinstance(v, (str, bytes)) Type guard
from collections.abc import Sequence
from typing import Any
def is_sequence_field(value: Any) -> bool:
return isinstance(value, Sequence) and not isinstance(value, (str, bytes)) Try / catch
from packaging.pylock import PylockValidationError
try:
PylockFile.from_dict(data)
except PylockValidationError as e:
if 'expected Sequence' in str(e):
wrap_in_array(e.context) Prevention
- Always use TOML array brackets for sequence fields.
- Validate sequence fields are not str/bytes before loading.
- Use a resolver rather than hand-writing TOML.
- Catch and surface e.context to the user.
When it happens
Trigger: Loading pylock.toml where 'dependencies = \"foo\"' (string instead of array), 'wheels = \"pkg.whl\"', or any array field is given a scalar string. The error context identifies the key.
Common situations: Hand-writing TOML and forgetting the array brackets; converting from a format that collapses single-element lists to scalars; typos like wheels = pkg.whl without quotes/brackets.
Related errors
- Unexpected type {type(value).__name__} (expected {expected_t
- Unexpected type {type(item).__name__} (expected {expected_it
- Hash values must be strings
- Invalid pylock file {pylock_path_or_url!r}: {exc}
- Name {name!r} is not normalized
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/ee86a88f9353c081.json.
Report an issue: GitHub.