Summary
When a user deletes their omi account, our backend wipes their Firestore data (including the users/{uid}/phone_numbers subcollection) but does not delete the corresponding verified caller IDs from Twilio. Those caller IDs remain registered to our Twilio account forever.
Impact
Twilio rejects any future attempt to verify a phone number that already has a caller ID on the account, regardless of which omi user previously owned it. So if user A verifies a phone number, deletes their account, and later user B (or A re-signing up with a new uid) tries to verify the same number, the /v1/phone/numbers/verify endpoint fails with error 21450 → "This phone number is already registered."
We hit this in production today — the only fix is an engineer manually calling Twilio's outgoing_caller_ids({sid}).delete() after confirming no live omi user owns the number.
Root cause
backend/routers/users.py:151 (delete_account) → spawns background delete_user_data in backend/database/users.py:646.
delete_user_data walks user subcollections and deletes Firestore docs, but never touches Twilio.
- Compare with
backend/routers/phone_calls.py:182 (remove_phone_number), which correctly calls delete_caller_id(twilio_sid) before deleting the Firestore record. The same teardown is missing on the account-deletion path.
Proposed fix
In the account-deletion background wipe, before the Firestore subcollection deletion runs, iterate users/{uid}/phone_numbers and call utils.twilio_service.delete_caller_id(twilio_sid) for each entry that has a twilio_sid set. Best-effort: log and continue on individual Twilio failures so a transient Twilio error can't block account deletion.
Acceptance criteria
- Deleting an account that has verified phone number(s) removes the corresponding caller IDs from Twilio.
- Twilio failures (network, 5xx, already-deleted) are logged but do not prevent the Firestore wipe from completing.
- Unit test covers: (a) cleanup called once per phone_numbers doc with a
twilio_sid, (b) docs without a twilio_sid are skipped, (c) a Twilio exception on one doc does not stop the others or the downstream wipe.
Out of scope
- Retroactive cleanup of caller IDs from already-deleted accounts (one-time ops task, not code).
Summary
When a user deletes their omi account, our backend wipes their Firestore data (including the
users/{uid}/phone_numberssubcollection) but does not delete the corresponding verified caller IDs from Twilio. Those caller IDs remain registered to our Twilio account forever.Impact
Twilio rejects any future attempt to verify a phone number that already has a caller ID on the account, regardless of which omi user previously owned it. So if user A verifies a phone number, deletes their account, and later user B (or A re-signing up with a new uid) tries to verify the same number, the
/v1/phone/numbers/verifyendpoint fails with error 21450 → "This phone number is already registered."We hit this in production today — the only fix is an engineer manually calling Twilio's
outgoing_caller_ids({sid}).delete()after confirming no live omi user owns the number.Root cause
backend/routers/users.py:151(delete_account) → spawns backgrounddelete_user_datainbackend/database/users.py:646.delete_user_datawalks user subcollections and deletes Firestore docs, but never touches Twilio.backend/routers/phone_calls.py:182(remove_phone_number), which correctly callsdelete_caller_id(twilio_sid)before deleting the Firestore record. The same teardown is missing on the account-deletion path.Proposed fix
In the account-deletion background wipe, before the Firestore subcollection deletion runs, iterate
users/{uid}/phone_numbersand callutils.twilio_service.delete_caller_id(twilio_sid)for each entry that has atwilio_sidset. Best-effort: log and continue on individual Twilio failures so a transient Twilio error can't block account deletion.Acceptance criteria
twilio_sid, (b) docs without atwilio_sidare skipped, (c) a Twilio exception on one doc does not stop the others or the downstream wipe.Out of scope