StripeError exceptions are not pickleable
メンテナーはふだん 2 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 55/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- python
調査の方向性
Start by locating StripeError and its subclasses, especially InvalidRequestError, and read how their constructors and exception arguments are handled. Reproduce the pickle round trip in the issue with Python 3.12, then inspect or add tests for serializing and deserializing the error. Done means the round trip succeeds for InvalidRequestError and its required fields are preserved.
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
StripeError exceptions can't be serialized and deserialized using pickle.
We use Celery and the errors returned by Stripe API calls can't be serialized and can't be caught outside of the async task.
To Reproduce
from stripe import StripeClient, InvalidRequestError
import pickle
try:
StripeClient("myapikey").v1.prices.list({"expand": ["notexpandable"]})
except InvalidRequestError as e:
pickle.loads(pickle.dumps(e)) # TypeError: InvalidRequestError.__init__() missing 1 required positional argument: 'param'
Expected behavior
InvalidRequestError can pickled:
pickle.loads(pickle.dumps(e))
raises no error
Code snippets
OS
Linux
Language version
Python 3.12
Library version
stripe-python v15.6.1
API version
2026-02-25.clover
Additional context
I suggest to not call the super().__init__() of the StripeError class. When the exception is pickled, it is deconstructed and reconstructed using the exc.args attribute, only the arguments passed to the parent class will be included in exc.args. For example:
class StripeError(Exception):
def __init__(message, http_body, http_status):
super().__init__(message)
....
StripeError("message", {"response": "body"}, 400).args # ("message",) all other arguments are not included
Solution:
class StripeError(Exception):
def __init__(message, http_body, http_status):
# do not call __init__ of Exception
....
StripeError("message", {"response": "body"}, 400).args # ("message", {"response": "body"}, 400)
But still if we pass keyword arguments:
class StripeError(Exception):
def __init__(message, http_body, http_status):
# do not call __init__ of Exception
....
# keyword arguments are not include in exception args
StripeError("message", http_body={"response": "body"}, status=400).args # ("message",)
We could think of passing all parameters to the parent class, but:
class StripeError(Exception):
def __init__(message, http_body, http_status):
# pass all parameters to parent class
super().__init__(message, http_body, http_status)
# instances of StripeError are fixed
StripeError("message", http_body={"response": "body"}, status=400).args # ("message", {"response": "body"}, 400)
# but what if we subclass again?
class InvalidRequesError(StripeError):
def __init__(message, http_body, http_status, param):
# pass all parameters to parent class
super().__init__(message, http_body, http_status)
self.param = param
# now we have an issue again
InvalidRequesError("message", {"response": "body"}, 400, "param").args # ("message", {"response": "body"}, 400) param is missing
One possible solution, never call Exception.init() and accept *args which will be forwarded to the parent class:
class StripeError(Exception):
# accept *args
def __init__(message, http_body, http_status, *args):
# do not call Exception.__init__()
...
# instances of StripeError are fixed
StripeError("message", {"response": "body"}, 400).args # ("message", {"response": "body"}, 400)
class InvalidRequesError(StripeError):
def __init__(message, http_body, http_status, param):
# pass all parameters to parent class
super().__init__(message, http_body, http_status, param)
self.param = param
# now also subclasses are fixed
InvalidRequesError("message", {"response": "body"}, 400, "param").args # ("message", {"response": "body"}, 400, "param")
If we want to subclass InvalidRequestError it will also have to accept *args and forward everything as positional argument to its parent class.
- 主要言語
- Python
- スター
- 2.1k
- フォーク
- 538
- 平均マージ
- 2日 16時間
- マージ済み PR(30日)
- 28
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
stripe/stripe-python のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
stripe/stripe-python#1936 · コメント 2 件 ·
メンテナーはふだん 2 日以内に返信
-
feature-request future
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
stripe/stripe-python#1886 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
feature-request
難易度 2/5 1〜3時間 初心者へのやさしさ 54/100
stripe/stripe-python#1841 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
feature-request future
難易度 3/5 1〜2日 初心者へのやさしさ 52/100
stripe/stripe-python#1812 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
Add async context manager support for AIOHTTPClient and HTTPXClient再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンfeature-request future
難易度 3/5 1〜2日 初心者へのやさしさ 74/100
stripe/stripe-python#1796 · コメント 3 件 ·
メンテナーはふだん 2 日以内に返信
stripe/stripe-python の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
pyjanitor-devs/pyjanitor#1758 ·
メンテナーはふだん 1 日以内に返信
-
bug ready for review
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
odysseus-dev/odysseus#6641 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
happypawspillaro/happypaws#78 ·
メンテナーはふだん 4 日以内に返信
-
pydanty:is-working
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
pydantic/pydantic-ai#10020 ·
メンテナーはふだん 1 日以内に返信
-
stdlib type-bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
python/cpython#159044 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信