{"id":"181034051a9d1387","repo":"boto/boto3","slug":"search-path-hits-shape-type-shape-type-name-from","errorCode":null,"errorMessage":"Search path hits shape type {shape.type_name} from {item}","messagePattern":"Search path hits shape type (.+?) from (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"boto3/resources/response.py","lineNumber":112,"sourceCode":"    response = None\n\n    operation_model = service_model.operation_model(operation_name)\n    shape = operation_model.output_shape\n\n    if search_path:\n        # Walk the search path and find the final shape. For example, given\n        # a path of ``foo.bar[0].baz``, we first find the shape for ``foo``,\n        # then the shape for ``bar`` (ignoring the indexing), and finally\n        # the shape for ``baz``.\n        for item in search_path.split('.'):\n            item = item.strip('[0123456789]$')\n\n            if shape.type_name == 'structure':\n                shape = shape.members[item]\n            elif shape.type_name == 'list':\n                shape = shape.member\n            else:\n                raise NotImplementedError(\n                    f'Search path hits shape type {shape.type_name} from {item}'\n                )\n\n    # Anything not handled here is set to None\n    if shape.type_name == 'structure':\n        response = {}\n    elif shape.type_name == 'list':\n        response = []\n    elif shape.type_name == 'map':\n        response = {}\n\n    return response\n\n\nclass RawHandler:\n    \"\"\"\n    A raw action response handler. This passed through the response\n    dictionary, optionally after performing a JMESPath search if one","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/boto/boto3/blob/c7b4afac237b976d48395d7523eaf7cec3a450b3/boto3/resources/response.py#L94-L130","documentation":"Raised by build_empty_response() when constructing an empty placeholder for a resource action whose JMESPath search_path traverses into a shape type other than 'structure' or 'list' (e.g. map, string, integer, blob). boto3 walks the dotted search path component by component to find the terminal shape so it can return the right empty value ({} , [], or None), and it only knows how to descend into structures and lists. Hitting any other shape type means the resource model's path definition is incompatible with this code, so it raises NotImplementedError rather than guessing.","triggerScenarios":"Calling a resource action (e.g. collection.batch_delete(), a custom action, or an action whose response path ends in a map/scalar) where the underlying service-model output shape along the configured search path is a map or primitive. It surfaces specifically when boto3 needs to synthesize an empty response (the operation returned nothing) and must resolve the terminal shape type via build_empty_response().","commonSituations":"Using a resource action against an older/newer API-version data file whose path no longer aligns with the service model; a resource model definition bug shipped in a boto3 version; pinning a botocore data version that mismatches the bundled boto3 resource definitions.","solutions":["Upgrade boto3 (and botocore) to the latest release so the bundled resource model and service model stay in sync: pip install -U boto3 botocore.","If you control the resource model / are developing one, shorten or correct the search_path so it terminates on a structure or list shape, or handle the scalar case upstream.","Switch from the resource API to the low-level client API (boto3.client(...).<operation>()) which does not run build_empty_response and returns the raw response dict.","If the error is consistent, file a boto3 issue with the service name, action, and boto3/botocore versions."],"exampleFix":"// before\nec2 = boto3.resource('ec2')\nresult = ec2.meta.client.some_action()  # triggers build_empty_response\n\n# after\nclient = boto3.client('ec2')\nresult = client.some_action()  # raw response, no empty-response shape walking","handlingStrategy":"try-catch","validationCode":"available = boto3.session.Session().get_available_resources()\nif service_name not in available:\n    client = boto3.client(service_name)  # avoid the resource path entirely","typeGuard":"def is_resource_supported(service_name: str) -> bool:\n    return service_name in boto3.session.Session().get_available_resources()","tryCatchPattern":"try:\n    result = resource.action()\nexcept NotImplementedError as e:\n    if 'Search path hits shape type' in str(e):\n        # resource model / data mismatch; fall back to client API\n        result = boto3.client(service_name).action()","preventionTips":["Keep boto3 and botocore versions in sync (pip install -U boto3 botocore) so resource models match service models.","Prefer the low-level client API for actions whose empty-response shape is uncertain.","Pin botocore to a version compatible with your pinned boto3 to avoid data/model drift."],"tags":["boto3","resource-api","internal","version-mismatch"],"analyzedSha":"c7b4afac237b976d48395d7523eaf7cec3a450b3","analyzedAt":"2026-08-04T20:35:51.598Z","schemaVersion":2}