Skip to content

v1.23.0 introduced "cannot pickle '_io.TextIOWrapper' object" error while trying to make a deep copy of request for lazy listeners #1284

@avnishpundir-plutoflume

Description

Our functional AWS lambda function, that's using slack-bolt, erroring out with following trace from today with upgrade to version 1.23.0 -

"exception_name": "TypeError",
    "stack_trace": {
        "type": "TypeError",
        "value": "cannot pickle '_io.TextIOWrapper' object",
        "module": "builtins",
        "frames": [
            {
                "file": "/var/lang/lib/python3.10/site-packages/slack_bolt/app/app.py",
                "line": 613,
                "function": "dispatch",
                "statement": "listener_response: Optional[BoltResponse] = self._listener_runner.run("
            },
            {
                "file": "/var/lang/lib/python3.10/site-packages/slack_bolt/listener/thread_runner.py",
                "line": 98,
                "function": "run",
                "statement": "self._start_lazy_function(lazy_func, request)"
            },
            {
                "file": "/var/lang/lib/python3.10/site-packages/slack_bolt/listener/thread_runner.py",
                "line": 185,
                "function": "_start_lazy_function",
                "statement": "copied_request = self._build_lazy_request(request, func_name)"
            },
            {
                "file": "/var/lang/lib/python3.10/site-packages/slack_bolt/listener/thread_runner.py",
                "line": 189,
                "function": "_build_lazy_request",
                "statement": "copied_request: BoltRequest = create_copy(request.to_copyable())"
            },
            {
                "file": "/var/lang/lib/python3.10/site-packages/slack_bolt/util/utils.py",
                "line": 47,
                "function": "create_copy",
                "statement": "return copy.deepcopy(original)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 172,
                "function": "deepcopy",
                "statement": "y = _reconstruct(x, memo, *rv)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 271,
                "function": "_reconstruct",
                "statement": "state = deepcopy(state, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 146,
                "function": "deepcopy",
                "statement": "y = copier(x, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 231,
                "function": "_deepcopy_dict",
                "statement": "y[deepcopy(key, memo)] = deepcopy(value, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 172,
                "function": "deepcopy",
                "statement": "y = _reconstruct(x, memo, *rv)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 297,
                "function": "_reconstruct",
                "statement": "value = deepcopy(value, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 172,
                "function": "deepcopy",
                "statement": "y = _reconstruct(x, memo, *rv)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 271,
                "function": "_reconstruct",
                "statement": "state = deepcopy(state, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 146,
                "function": "deepcopy",
                "statement": "y = copier(x, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 231,
                "function": "_deepcopy_dict",
                "statement": "y[deepcopy(key, memo)] = deepcopy(value, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 172,
                "function": "deepcopy",
                "statement": "y = _reconstruct(x, memo, *rv)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 271,
                "function": "_reconstruct",
                "statement": "state = deepcopy(state, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 146,
                "function": "deepcopy",
                "statement": "y = copier(x, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 231,
                "function": "_deepcopy_dict",
                "statement": "y[deepcopy(key, memo)] = deepcopy(value, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 172,
                "function": "deepcopy",
                "statement": "y = _reconstruct(x, memo, *rv)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 271,
                "function": "_reconstruct",
                "statement": "state = deepcopy(state, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 146,
                "function": "deepcopy",
                "statement": "y = copier(x, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 231,
                "function": "_deepcopy_dict",
                "statement": "y[deepcopy(key, memo)] = deepcopy(value, memo)"
            },
            {
                "file": "/var/lang/lib/python3.10/copy.py",
                "line": 161,
                "function": "deepcopy",
                "statement": "rv = reductor(4)"
            }
        ]
    },

We do have a lazy handler as part of this flow that stopped working (with above exception in our logs). The lazy handler is as follows -

def register_slack_handlers(app: App):
    # REQUEST_FORM_SUBMITTED is a constant defined in our system
    app.view(REQUEST_FORM_SUBMITTED)(
        ack=slack_new_req_ack, lazy=[handle_submission]
    )

This block was working well till few days back. Once we locked down the slack-bolt to 1.22.0, the error disappeared and everything started to work as it was. I believe there's a broken change in the deep copy logic that introduced this bug in 1.23.0.

Reproducible in:

$ pip freeze | grep slack
slack_bolt==1.23.0
slack_sdk==3.35.0

$ python --version
Python 3.10.14

# sw_vers && uname -v # or `ver`
# It's AWS lambda environment for python 3.10

The slack_bolt version

slack_bolt==1.23.0
slack_sdk==3.35.0

Python runtime version

Python 3.10.14

OS info

AWS Lambda python 3.10 runtime

Steps to reproduce:

N/A

Expected result:

the lazy handler continue to work as-is for version 1.23.0 onwards.

Actual result:

It's broken, full trace already shared in the ticket.

Requirements

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions