Privacy mistakes
Every mistake on this page happened in a real system. Each one cost a store rejection, a compliance gap, or a long investigation. Read the whole list in your first week. Each item links to the page with the fix.
How it works
Most mistakes below are one of five patterns. When you review a privacy change, ask the five questions: was the control there first, is there one source of truth, was the claim checked, would a failure be visible, and is it configured in production?
Consent
- Analytics on at boot for everyone. One line enabled analytics before any screen, for guests too. Gate SDKs on the stored decision. Consent model
- A purpose the server did not know. The app sent a new AI consent purpose; the server registry lacked it, rejected every grant, and recorded nothing. The log line dropped the offending value. Seed server first; log what failed. Consent model
- A fix that would have re-asked every user. Adding a purpose to the shared first-run notice would have bumped its version for the whole base. One notice version per surface. Consent model
- Consent copy editable over the air. Translation bundles could change what users agreed to without a release, and the lock everyone assumed existed was never built. Consent model
- "We never share your messages" while hashes of queries went to analytics. Hashed still means shared. Consent model
- A client-sent copy hash. Proves nothing. The server owns and hashes the copy. Consent model
- Bundled tick on a public form. Terms, requested processing and marketing in one box. Split into a mandatory and an optional tick. DPDP
- Withdrawal harder than the grant. One click to give, an email and ID check to withdraw. Use a signed withdrawal link. DPDP
- Uploads before consent. Files reached storage before the tick, and abandoned ones stayed forever. DPDP
Marketing
- Marketing on the sign-in email account. A complaint could suppress the address account-wide and silently drop sign-in codes. Marketing and email
- One shared opt-in purpose with no grants. An opt-in-only campaign would reach nobody. Decide the basis per product before launch. Marketing and email
- Unsubscribe without a campaign id. Nobody could tell which email drove the opt-out. Marketing and email
- A bulk send by script. It skipped a consent flag and wrote no send log. Marketing and email
- Emails uploaded to an ad platform by hand. No consent, no disclosure, no record of who was in which upload. Marketing and email
- No DMARC record. Bulk mail gets filtered and spoofing is invisible. Marketing and email
AI
- Store rejection for sending data to an AI with no in-app ask. Policy text alone was not enough. AI processing
- "The provider does not train on your data" before checking the tier. AI processing
- The policy named the wrong AI platform and missed two moderation providers. Data map and RoPA
Deletion and requests
- Fire-and-forget erasure. A failing subscriber was logged once and never retried, leaving half-deleted accounts. Data subject requests
- The AI erase relay was enabled in dev only. Deleted users' chat transcripts stayed in production. AI processing
- Many tables had no erase. The policy promised deletion that the code did not do. Data subject requests
- Avatars unlinked, not deleted, in a versioned bucket. Retention and deletion
- Processors never told to delete. Auth provider, analytics, attribution, crash tools. Data subject requests
- A checklist step that told staff the wrong thing. Data subject requests
- The policy's deletion link went to a page that did not exist. Data subject requests
- Exporting data we could not delete. Hold back an export section until its erase exists. Data subject requests
Retention and logs
- Purge jobs scheduled in dev only. Retention and deletion
- Log groups with no retention, kept forever. Retention and deletion
- User tokens in URL query strings and a service key written to logs. The key had to be rotated. Breach response
- Manual database snapshots that never expired, keeping erased users alive. Retention and deletion
- Raw email and phone inside cache key names. Retention and deletion
- A code comment promised an S3 lifecycle backstop that did not exist. Data map and RoPA
- An unsalted hash described as anonymous. Retention and deletion
Children and age
- The minimum age hard-coded in nine places. Children's data
- Branching on English error text broke the "too young" message. Children's data
- A database constraint added as NOT VALID grandfathered under-age rows. Children's data
- An age decision that never reached the terms. Children's data
- Attribution SDK and push registration before the age gate. Children's data
Data map and law
- "Personal data regional, content global" was not true; a raw device ID sat in the global tier with no erasure path. Data map and RoPA
- Disclosure offered as the fix for an unlawful transfer. GDPR
- Region chosen from device language, and unknown countries fell through silently. GDPR vs DPDP
- A new policy version silently lost its shared sections, including the grievance contact. Staying current
- Store review bypass code committed to a repository. Breach response
Rules
Rule
When you find a privacy mistake, add it here and to the page it belongs on, in the same pull request as the fix. A lesson that lives only in chat is lost.
Checklist
- You have read every item on this page.
- Your current feature does not repeat any of the five root causes.