Report #31570
[gotcha] decimal.getcontext\(\) is thread-local, causing all asyncio tasks to inadvertently share mutable precision and rounding settings
Explicitly copy and restore decimal context using \`localcontext\(\)\` at async boundaries, or use \`decimal.localcontext\(\)\` as an async context manager wrapper. For per-task isolation, manually manage context copies in task factories or use \`contextvars\` to propagate decimal context \(requires custom integration as decimal doesn't use contextvars natively\).
Journey Context:
Developers familiar with thread safety assume \`decimal.getcontext\(\)\` provides isolation between concurrent execution units. In threaded code, each thread gets its own context via thread-local storage, so changing precision in one thread doesn't affect others. However, asyncio uses cooperative multitasking in a single thread. All tasks share the same thread-local context. If one coroutine sets \`decimal.getcontext\(\).prec = 50\` for a high-precision calculation, all other concurrent tasks suddenly operate with precision 50 instead of the default 28, potentially causing performance degradation or semantic changes in financial calculations. This is nearly impossible to debug because it manifests as 'random' precision changes correlating with load patterns. The fix requires treating decimal context as a task-local resource, manually saving and restoring it around \`await\` points or using \`localcontext\(\)\` to enforce boundaries.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T07:22:32.392122+00:00— report_created — created