Troubleshooting
Questa pagina raccoglie i casi ricorrenti di "l'utente segnala X" e le query
di runbook che li diagnosticano. Tutte le query girano sul progetto Supabase
del Contributor Portal (xlsjwlmsqonllvtyplml) salvo diversa indicazione.
Tip: nell'MCP Supabase
playroll_supa_portal, incolla le query direttamente. Sono scritte in modo che l'unica cosa che cambia per ogni caso sia l'email in cima.
"Non mi è arrivata la mail di conferma IBAN"
Il singolo report più frequente. Sintomi: l'utente ha completato il form IBAN ma non ha ricevuto il magic link di conferma; oppure l'ha ricevuto ma adesso dice "link scaduto".
Step 1 — l'utente esiste in auth?
select id, email, created_at, last_sign_in_at,
email_confirmed_at, confirmation_sent_at, recovery_sent_at
from auth.users
where email = 'user@example.com';
Se è vuoto, l'utente non è mai arrivato a signInWithOtp. Digli di
ritentare il flusso da zero e di guardare console / network tab del
browser per cercare errori. Probabilmente un ad-blocker o una rete
problematica.
Step 2 — qual è lo stato del suo payout method?
select id, method_type, status, email_confirmation_status,
email_confirmation_sent_at, email_confirmed_at,
iban_last4, created_at, updated_at
from public.payout_receiving_methods
where lower(verified_email) = 'user@example.com'
order by created_at desc;
Stati possibili:
status | email_confirmation_status | Significato |
|---|---|---|
pending_email_confirmation | pending | La mail è stata inviata. Il link che ha cliccato era probabilmente scaduto. Digli di richiedere un nuovo link di conferma dal portale (dovrà rifare il login e re-inviare). |
confirmed | confirmed | Tutto a posto. È confuso — rimandalo al portale per vedere il badge verde. |
manual_review | n/a | Percorso manual review, non un caso di conferma email. |
| (nessuna riga) | Non ha mai inviato l'IBAN. |
Step 3 — cosa dice la telemetria?
with hash as (
select public.telemetry_email_hash('user@example.com') as eh
)
select occurred_at, event_name, severity, error_code, error_message, attrs
from public.telemetry_events, hash
where telemetry_events.email_hash = hash.eh
or telemetry_events.auth_user_id = (
select id from auth.users where email = 'user@example.com'
)
order by occurred_at desc
limit 50;
Cerca la sequenza:
payout.receiving_method.submitted— ha cliccato "Save IBAN"auth.otp.requested(intent: payout) — il portale ha chiesto a Supabase Auth di inviare il magic linkauth.otp.sent— Supabase Auth ha confermato l'inviopayout.receiving_method.confirmed— ha cliccato il link
Se 1+2 sono presenti ma 3 no, Supabase Auth ha rifiutato (rate-limit,
errore SMTP). Controlla auth.audit_log_entries (caso successivo).
Caso reale (Philip, 2026-05-03): ha inviato l'IBAN, la mail è stata inviata con successo, ma il link è rimasto nel tab Promozioni di Gmail non letto per 11 giorni. Quando gli è stato chiesto di controllare lo spam l'ha trovato. Nessuna modifica di codice necessaria.
"L'app PlayRoll dice ancora 'Not verified' anche se ho finito sul portale"
Il portale completa il bridge scrivendo in contributor_status_projection
sul progetto Supabase app (vtyolotvuvlbvqbgbzde). I due flussi
(app-first / portal-first) falliscono in
modi diversi.
Modalità A — codice di attivazione portal-first mai redento. Se l'utente si è registrato sul portale senza passare dal pulsante "Collega account" dell'app, deve generare un codice di attivazione sul portale (sezione Rewards → "Genera codice") e incollarlo nell'app (Settings → Account contributor → Riscatta). Finché non lo fa, nessuno Steam ID è collegato e il badge rimane "Not verified".
-- portal: did they ever generate a code?
select id, status, issued_at, expires_at, redeemed_at, redeemed_app_user_id
from public.recorder_activation_codes
where portal_auth_user_id = (
select id from auth.users where email = 'user@example.com'
)
order by issued_at desc;
Se status = 'issued' e expires_at > now() ha un codice valido ma
non l'ha mai incollato nell'app. Se status = 'expired' o tutte le
righe sono revoked, guidalo a generarne uno nuovo. Se status = 'redeemed' il bridge è già partito — salta alla Modalità B più sotto.
Modalità B — il bridge è partito ma non ha attivato. Controlla entrambi i progetti:
-- portal (xlsjwlmsqonllvtyplml)
select id, status, app_user_id, intent_nonce, linked_at
from public.contributor_app_links
where portal_auth_user_id = (
select id from auth.users where email = 'user@example.com'
);
-- app (vtyolotvuvlbvqbgbzde)
select * from public.contributor_status_projection
where app_user_id = '<the app_user_id from above>';
Se la riga del portale è pending_activation, il gate (onboarding
inviato + payout confermato) non era completo quando l'attivazione è
partita. Di' all'utente di completare lo step mancante e ricaricare il
portale — il dedup hook ritenterà entro ~30s dal soddisfacimento del
gate.
Se la riga del portale è active ma la riga app manca, la scrittura
cross-project è fallita. Questo è un bug reale e serve un ingegnere:
controlla i log della edge function activate-contributor-app-link
attorno al timestamp di attivazione.
"Vedo errori a caso nella console del portal"
Il portale emette eventi ui.unhandled_error, ui.unhandled_rejection e
ui.error_boundary nella stessa tabella telemetry_events. Crash recenti:
select occurred_at, event_name, attrs->>'scope' as scope,
error_message, attrs->>'component_stack' as component_stack
from public.telemetry_events
where event_name like 'ui.%'
and severity in ('error', 'fatal')
and occurred_at > now() - interval '1 hour'
order by occurred_at desc;
Raggruppa per error_message per individuare bug ricorrenti:
select error_message, count(*) as occurrences,
count(distinct session_id) as affected_sessions,
max(occurred_at) as last_seen
from public.telemetry_events
where event_name = 'ui.error_boundary'
and occurred_at > now() - interval '7 days'
group by error_message
order by occurrences desc;
"Una mia chiamata Supabase è in errore ma non vedo niente in UI"
Non dovrebbe più accadere dopo EC-189: i quattro helper di lettura
(loadLatestApplication, loadLatestOnboardingSubmission,
loadLatestPayoutReceivingMethod, loadContributorDashboard) ora mostrano
un toast tramite showSupabaseError() ed emettono telemetria
ui.toast.shown.
Se una chiamata di scrittura (insert/update/RPC) restituisce un errore
e l'utente non vede nulla, è un bug — controlla l'handler di submit del
form in src/features/portal/usePortalFlow.ts, l'errore è probabilmente
mangiato.
"Voglio vedere il funnel onboarding negli ultimi giorni"
select date_trunc('day', occurred_at) as day,
event_name,
count(distinct auth_user_id) as users
from public.telemetry_events
where event_name in (
'auth.otp.requested',
'auth.otp.sent',
'payout.receiving_method.submitted',
'payout.receiving_method.confirmed',
'app_link.activate.verified'
)
and occurred_at > now() - interval '7 days'
group by day, event_name
order by day desc, event_name;
Cerca grandi salti tra uno step e il successivo — è lì che gli utenti stanno abbandonando.