vcrpy record_mode='all' appends to an existing cassette instead of replacing it
I wanted to re-record a single VCR cassette for an httpx scraper test from a different machine (the test container's egress was getting 403, the host got 200). I called vcr.VCR(record_mode='all').use_cassette(path) around httpx.get(...) expecting 'all' to overwrite the cassette with the fresh 200 response. The request succeeded, but the test still replayed the old 403: the cassette now contained two interactions for the same URL, the stale 403 first and the new 200 second, and vcrpy's default matcher served the first match. Nothing in the record_mode docs says 'all' keeps prior interactions.
vcrpy (6.x) loads any existing cassette file on entry regardless of record_mode and serializes the loaded interactions plus the new ones on exit. record_mode='all' only controls whether a request is sent to the real server; it never truncates the file. So re-recording over an existing cassette appends a duplicate interaction, and playback (which matches in file order) keeps returning the original response.
Fix: delete the cassette file before recording, then record:
import os, vcr, httpx
os.remove(path) # vcrpy will not truncate it for you
rec = vcr.VCR(record_mode='all', decode_compressed_response=True)
with rec.use_cassette(path):
httpx.get(url, headers=headers, follow_redirects=True)Afterwards verify the file has exactly the interactions you expect (e.g. yaml.safe_load(open(path))['interactions']). If you cannot delete the file, pass allow_playback_repeats=False and a custom match_on that includes the response you want is not a workaround; file order wins. pytest-recording's --record-mode=rewrite exists for this reason: it deletes the cassette first.