Your script renames Korean filenames on a Mac and not a single name changes. Your GA4 traffic report shows odd sources like tab or (not set). You push the same commit to a new branch to retrigger a Vercel preview deployment and nothing happens. A table fed by a daily public-data collector slowly fills with the same transaction twice. None of these raise an error. Your script or agent reports success.
Why do writes get ignored or overwritten without an error?
Every system that accepts your writes has its own rule for deciding what counts as "the same thing", and when that rule disagrees with yours, the write is silently ignored, overwrites someone else's value, or piles up as a duplicate. A file system decides by Unicode normalization, an analytics tool by reserved parameter names, a deploy integration by commit hash, a database by the idempotency key you defined. If the receiver thinks it already has it, there is nothing to do. If it sees the same name, it overwrites. If it sees something different, it inserts. All three are normal behavior on the receiving side, so there is no reason for it to raise an error.

Which rules decide what is "the same"?
Four come up most often.
- Unicode normalization (file systems). A Korean syllable can be stored as one precomposed character (NFC) or as separate jamo (NFD); accented Latin letters work the same way. The Mac file system treats both as the same name. So asking it to rename an NFD file to the NFC spelling does nothing — "it already has that name." The byte-different name stays, and the next step that parses categories out of filenames breaks. The normalization forms are defined in Unicode Standard Annex #15.
- Reserved names (analytics). Attach a parameter called
sourceto a GA4 event and GA4 reads it as the traffic source, not as your event property. The value you meant as "which tab was this clicked in" overwrites that session's acquisition source.mediumandcampaignbehave the same way. - Commit hash (deploy integrations). A Git-connected deployment that has already seen a commit SHA will not build it again — not from another branch, not after a force-push moves the branch tip. There isn't even a "skipped" entry, so the integration looks dead.
- Idempotency key (databases). If the key you built to avoid inserting a record twice includes a field the source fills in later (a registration number added weeks afterwards, say), the day that field is filled the same record becomes "different" and goes in as a new row.
In the first three the receiver called things "the same" more broadly than you did; in the last, your own key called things "the same" too narrowly. Opposite directions, same symptom: no error, wrong result.
What should you check before writing?
Run through this list whenever you write names or keys into a new system.
- What does the receiver compare to decide identity? Raw bytes, normalized characters, case-insensitive text, a hash, or a key you defined?
- Does your name collide with a reserved one? Where a system gives special meaning to certain names (analytics tools, mail headers, form fields, environment variables), avoid generic words (
source,type,name,id) and add a prefix (ui_source,click_origin). - Does your key include a field that changes later? Put only fields that are fixed from the start into an idempotency key. If you truly need a late-filled field, pair it with a rule that deletes the blank row when the filled row arrives.
- Does "do it again" really look new to the receiver? For anything where you resend the same input expecting a rerun (redeploys, cache invalidation), check whether the receiver treats it as new input. If not, change the input — even an empty commit.
What should you count after writing?
A success response means "received", not "changed". Count the result yourself.
- After renaming, re-read the listing and compare byte by byte (if the length differs before and after normalization, it is still NFD).
- After sending events, check that sessions carrying that event did not change acquisition source in the report.
- After redeploying, check that a new entry appeared in the deployment list.
- After collecting, count duplicates on the key minus its changing fields.
If an agent does this work, put this in its instructions:
When writing names or keys into an external system:
- First confirm how the receiver decides two things are the same (normalization, case, reserved names, hash, idempotency key).
- Do not use generic words (source, medium, campaign, type, name) as parameter names. Add a prefix.
- Do not report a success response as the result. Re-read after the write, count what actually changed, and report that count.
- When renaming files to NFC on macOS, go through a temporary name (rename twice).
What happened to us
- Filename cleanup (macOS, APFS). Renaming NFD-stored Korean filenames to their NFC spelling did nothing. Renaming once to a temporary name and then to the NFC name normalized them. Until then, an upload step that parsed categories from filenames was broken.
- GA4 traffic source. A button-click event carried the tab name in a
sourceparameter; the sessions that clicked had their acquisition source replaced by the tab name, so sources liketabappeared in the report. Renaming the parameter made them disappear. - Git-connected deployment. To retrigger a preview we force-pushed the same commit and pushed it to a new branch; no deployment appeared and no skip was logged. Adding a new commit built it.
- Transaction collector. A field the source fills in later was part of the idempotency key, so the moment it was filled, the same transaction came in as a new row and duplicates quietly piled up. We removed that field from the key and made the filled row delete its blank twin (rows with a different status, such as cancellations, are kept as separate records).
Every one of the four returned success. We noticed only when we counted the result again — the file listing, the report's source column, the deployment list, the duplicate count.
PreviousA deploy is a cache wipe — on sites that render on request, measure which cache layers survive a deploy and count deploys as cost