Skip to content

Potential AttributeError in scan/async_scan when query is a non-dict Mapping type #3448

Description

@jubins

Elasticsearch version: N/A (client-side issue)

Python version: All supported versions

Description:

The scan() and async_scan() functions have a potential bug where they unconditionally call .copy() on the query object, which may not support this method if it's a Mapping type that isn't a dict.

Current code:

Sync version:

query = query.copy() if query else {}

Async version:

query = query.copy() if query else {}

if not preserve_order:
    query = query.copy() if query else {}  # Could fail if query is a Mapping without .copy()
    query["sort"] = "_doc"

Problem: If a user passes a query that is a collections.abc.Mapping subclass (not a dict) that doesn't implement a .copy() method, this will raise an AttributeError. This exception is NOT caught by the existing try/except block which only catches TypeError.
Expected behavior: The function should handle any Mapping-like object safely, converting it to a dict if necessary before attempting to modify it.

Suggested fix:

if not preserve_order:
    if query:
        if isinstance(query, dict):
            query = query.copy()
        else:
            # Convert to dict for non-dict Mapping types
            query = dict(query)
    else:
        query = {}
    query["sort"] = "_doc"

Steps to reproduce:

from collections.abc import MutableMapping
from elasticsearch.helpers import scan

class CustomMapping(MutableMapping):
    def __init__(self):
        self.data = {"match_all": {}}
    # ... implement required methods but NOT .copy()

client = Elasticsearch(...)
query = CustomMapping()
# This would raise AttributeError
list(scan(client, index="test", query=query, preserve_order=False))

Affected files:
Sync:

query = query.copy() if query else {}

Async:
query = query.copy() if query else {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions