Skip to content

Commit ffc0309

Browse files
authored
fix(start): lazy-init languages on /start to unblock cold-start orphans (#222)
Sega (#370728472) hit /start, immediately got "memes ended". Root cause: no rows in user_language for him → recommendations query filters every candidate out → cold start surfaces the empty-feed message. How he ended up there: he registered on 2026-04-01 with deep_link 'kitchen'. The kitchen branch in handle_start returns BEFORE any init_user_languages_from_tg_user call: if deep_link == "kitchen": return await handle_show_kitchen(update, context) The wrapped + main "if created" branches both call init; kitchen silently skipped it. Six new users in the last 30 days (4 via 'kitchen', 2 via deep_link=None) ended up the same way — all backfilled by hand just now. Fix: hoist a single idempotent check above the deep_link branching: if not await get_user_languages(user_id): await init_user_languages_from_tg_user(update.effective_user) This covers every branch (current + future deep_links) and self-heals any historical orphan the next time they /start. Removed the per-branch init calls in wrapped + new-user paths since the new check supersedes them. Idempotent guarantee: add_user_languages uses ON CONFLICT DO NOTHING. Note on extent: 893 historical orphans exist (mostly pre-init code), but only 6 were active in the last 30d / 3 in the last 7d — the bug was not blocking the main onboarding funnel (38/38 new users in last 7d had languages). It was a long-tail correctness issue that bit any share-link / deep-link path that returned early.
1 parent 6df40d3 commit ffc0309

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

src/tgbot/handlers/start.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from src.tgbot.service import (
2222
create_or_update_user,
2323
get_tg_user_by_id,
24+
get_user_languages,
2425
log_user_deep_link,
2526
save_tg_user,
2627
)
@@ -102,18 +103,23 @@ async def handle_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
102103
created,
103104
)
104105

106+
# Ensure language rows exist before any branch that may serve memes.
107+
# Covers: new users on every deep_link path (kitchen used to skip init),
108+
# and historical orphans whose init was never run — they were stuck on
109+
# "memes ended" because recommendations filter by user_language.
110+
# Idempotent: add_user_languages uses ON CONFLICT DO NOTHING.
111+
if not await get_user_languages(user_id):
112+
await init_user_languages_from_tg_user(update.effective_user)
113+
105114
if deep_link == "kitchen":
106115
return await handle_show_kitchen(update, context)
107116

108117
if deep_link == "wrapped":
109118
from src.tgbot.handlers.stats.wrapped import handle_wrapped
110119

111-
if created:
112-
await init_user_languages_from_tg_user(update.effective_user)
113120
return await handle_wrapped(update, context)
114121

115122
if created: # new user:
116-
await init_user_languages_from_tg_user(update.effective_user)
117123
await handle_language_settings(update, context)
118124

119125
await handle_invited_user(

0 commit comments

Comments
 (0)