#486

steam: propagate local depot write errors without retrying healthy CDNs

OpenJelly-RayTianwants to merge intofrom

A verified depot chunk is currently written inside the CDN retry catch. If opening or writing the local game file fails (for example, storage exhaustion, an unavailable folder or a non-seekable destination), the downloader penalizes the content server and fetches the same chunk again. Retrying cannot repair local storage, wastes bandwidth and delays the original error.

Keep download/decode/size validation inside the existing retry boundary. Once the chunk is verified, record the host's success and write outside that boundary, so local file errors propagate immediately. Network/decode/checksum retries and cancellation remain handled by the same existing catch logic. A failed write still cannot return a completed work item, so it is not journaled as a finished chunk. No server selection, licensing, encryption, resume format, background policy or submodule change is included.

Validation:

  • python3 tests/host/check-depot-write-failures.py: production fetch/retry, POSIX write and ContentHostHealth code compile and execute under AddressSanitizer. On unchanged main, four assertions fail: both open failure (real ENOENT) and post-open write failure (real ESPIPE, using a temporary FIFO with its reader open) download three times and demote a healthy host. Patched code downloads once, preserves the exact original error and leaves the host order unchanged.
  • Regression also passes successful offset writes, transient network/decode/size failures, cancellation with no file write or host penalty, and persistent network failure exhausting exactly three attempts. Network/decryption are deterministic test fixtures; no live CDN, Steam account or cryptographic validation is claimed by this harness.
  • The extracted production functions and host-health code also type-check for iOS arm64, SDK 26.5, with no diagnostics. This is a source-unit check, not a full app build or iPad result.
  • git diff --check passes.

Broader validation limitation: python3 tests/host/check-steam-library.py stops while generating its Zstandard fixtures with ModuleNotFoundError: No module named 'compression'. Its from compression import zstd needs Python 3.14; this Mac currently has Python 3.9/3.11. The broad suite was attempted but did not run to completion, and no replacement compressor or test bypass was added.

Based on current main c2c1b03a. Checked the open DLC PR #484; it still has the same local-write retry boundary, so this does not duplicate its DLC implementation. AI-assisted implementation and host testing.