My FastAPI application synchronizes a user's scrobbles from the Last.fm API using Python's requests library. The sync works consistently when run directly on my EndeavourOS host, but when the same application runs in a Python 3.12 slim container, response.json() randomly raises JSONDecodeError during pagination.
I inspected the raw response.content and found that the corruption already exists in the received bytes, so this does not appear to be a text-decoding problem. Otherwise-valid ASCII bytes are being changed by setting their highest bit while leaving the other bits untouched. For example, 0x22 (a quote) becomes 0xa2, 0x2f becomes 0xaf, 0x30 becomes 0xb0, and 0x65 becomes 0xe5. The affected page varies, but the same sync reliably succeeds outside the container.
The application uses HTTPS, and the container is built from python:3.12-slim-bookworm with Docker Compose. What could cause this kind of deterministic bit-7 corruption, and what should I investigate next?
3 Answers
The Python image should use UTF-8 by default, but encoding cannot explain this symptom because the altered values are already present in `response.content`, before `response.text` or `response.json()` decodes anything. Compare the raw bytes from the same URL in a minimal container and on the host, and log the process and system details, but the consistent bit-7 transformation points much more toward memory or hardware instability.
This pattern strongly suggests a hardware problem rather than Docker or requests. Every affected byte is being changed with a bitwise OR of 0x80, which looks like a stuck or unstable bit in memory, a CPU cache, or the memory controller. The container may simply be causing allocations to land in a physical memory region that the host process does not use.
Network corruption is unlikely: TCP checksums and HTTPS authentication should prevent damaged payloads from being delivered as silently altered plaintext. Compression errors would also normally cause decompression failures instead of clean JSON containing isolated bit flips.
Run memtest86+ from a bootable system and let it complete multiple passes, ideally overnight. Also check for hardware error reports with commands such as `dmesg | grep -iE 'mce|edac|memory error|hardware error'` and `journalctl -k` with similar filters. If memory overclocking or XMP is enabled, temporarily return the system to conservative JEDEC settings. Test each DIMM separately if possible.
Docker's virtual networking should not modify application payloads. TCP and HTTPS integrity checks make an on-the-wire bit flip very unlikely, and pseudo-terminal settings only affect displayed terminal output, not bytes stored in an HTTP response object. A second machine working normally is useful evidence against the API and toward the original system's RAM, CPU, or memory-controller path.

I tried the same workload on another Linux machine and have not seen any corrupt responses there, so a problem with the original machine seems increasingly likely. Unfortunately, that makes container-based development on it unreliable until the hardware is tested.