{"record":{"id":"21bf6f737f102a10","repo":"pypa/pip","slug":"unexpected-type-type-value-name-expected","errorCode":null,"errorMessage":"Unexpected type {type(value).__name__} (expected {expected_type.__name__})","messagePattern":"Unexpected type (.+?) \\(expected (.+?)\\)","errorType":"validation","errorClass":"DirectUrlValidationError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/direct_url.py","lineNumber":52,"sourceCode":"\nclass _FromMappingProtocol(Protocol):  # pragma: no cover\n    @classmethod\n    def _from_dict(cls, d: Mapping[str, Any]) -> Self: ...\n\n\n_FromMappingProtocolT = TypeVar(\"_FromMappingProtocolT\", bound=_FromMappingProtocol)\n\n\ndef _json_dict_factory(data: list[tuple[str, Any]]) -> dict[str, Any]:\n    return {key: value for key, value in data if value is not None}\n\n\ndef _get(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T | None:\n    \"\"\"Get a value from the dictionary and verify it's the expected type.\"\"\"\n    if (value := d.get(key)) is None:\n        return None\n    if not isinstance(value, expected_type):\n        raise DirectUrlValidationError(\n            f\"Unexpected type {type(value).__name__} \"\n            f\"(expected {expected_type.__name__})\",\n            context=key,\n        )\n    return value\n\n\ndef _get_required(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T:\n    \"\"\"Get a required value from the dictionary and verify it's the expected type.\"\"\"\n    if (value := _get(d, expected_type, key)) is None:\n        raise _DirectUrlRequiredKeyError(key)\n    return value\n\n\ndef _get_object(\n    d: Mapping[str, Any], target_type: type[_FromMappingProtocolT], key: str\n) -> _FromMappingProtocolT | None:\n    \"\"\"Get a dictionary value from the dictionary and convert it to a dataclass.\"\"\"","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/direct_url.py#L34-L70","documentation":"_get() is a helper used by DirectUrl.from_dict() and related _from_dict methods to retrieve and type-check fields from a PEP 610 direct_url.json mapping. If a value exists but its Python type does not match the expected type, DirectUrlValidationError is raised with the actual and expected type names and the field key as context. This is the primary type-validation guard for the direct URL JSON structure.","triggerScenarios":"Calling DirectUrl.from_dict(d) where a field has the wrong JSON type: url is a number, subdirectory is a list, editable is a string 'true' instead of boolean true, or vcs/commit_id are non-strings.","commonSituations":"Hand-edited direct_url.json files. Broken pip metadata in installed packages. Programmatic generation of direct URL JSON without type checking.","solutions":["Ensure all fields in direct_url.json match PEP 610 types: strings for url/vcs/commit_id, bool for editable, objects for info blocks","Validate the JSON dict types before passing to from_dict","Use to_dict() to generate correctly-typed JSON rather than hand-crafting it"],"exampleFix":"# before\ndata = {\"url\": 12345, \"dir_info\": {\"editable\": \"true\"}}  # wrong types\nDirectUrl.from_dict(data)  # raises\n\n# after\ndata = {\"url\": \"file:///path/to/project\", \"dir_info\": {\"editable\": True}}\nDirectUrl.from_dict(data)","handlingStrategy":"validation","validationCode":"def validate_direct_url_types(d: dict) -> None:\n    if \"url\" in d and not isinstance(d[\"url\"], str):\n        raise TypeError(\"url must be a string\")\n    if \"subdirectory\" in d and not isinstance(d[\"subdirectory\"], str):\n        raise TypeError(\"subdirectory must be a string\")\n    for key in (\"archive_info\", \"vcs_info\", \"dir_info\"):\n        if key in d and not isinstance(d[key], dict):\n            raise TypeError(f\"{key} must be a dict/object\")\n    if \"dir_info\" in d and \"editable\" in d[\"dir_info\"]:\n        if not isinstance(d[\"dir_info\"][\"editable\"], bool):\n            raise TypeError(\"dir_info.editable must be a bool\")","typeGuard":"def is_valid_direct_url_dict(d) -> bool:\n    return (\n        isinstance(d, dict)\n        and isinstance(d.get(\"url\", \"\"), str)\n        and all(\n            isinstance(d.get(k), dict)\n            for k in (\"archive_info\", \"vcs_info\", \"dir_info\")\n            if k in d\n        )\n    )","tryCatchPattern":"from packaging.direct_url import DirectUrl, DirectUrlValidationError\n\ntry:\n    du = DirectUrl.from_dict(data)\nexcept DirectUrlValidationError as e:\n    print(f\"Invalid direct_url.json: {e}\")","preventionTips":["Never hand-edit direct_url.json; use to_dict()","Validate JSON types before parsing","Schema-validate PEP 610 metadata files"],"tags":["packaging","pep610","json-validation","direct-url","vendored"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}