{"record":{"id":"97ba4e4978afc035","repo":"Stirling-Tools/Stirling-PDF","slug":"supabase-is-not-configured","errorCode":null,"errorMessage":"Supabase is not configured","messagePattern":"Supabase is not configured","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/proprietary/auth/supabase/supabaseClient.ts","lineNumber":49,"sourceCode":"    auth: {\n      persistSession: config.authOptions?.persistSession ?? true,\n      autoRefreshToken: config.authOptions?.autoRefreshToken ?? true,\n      detectSessionInUrl: config.authOptions?.detectSessionInUrl ?? true,\n    },\n  });\n  return client;\n}\n\n/** The configured Supabase client, or null if not configured. */\nexport function getSupabaseClient(): SupabaseClient | null {\n  return client;\n}\n\n/** Anonymous (guest) sign-in. Throws if Supabase is not configured. */\nexport async function signInAnonymously() {\n  const supabase = getSupabaseClient();\n  if (!supabase) {\n    throw new Error(\"Supabase is not configured\");\n  }\n  return supabase.auth.signInAnonymously();\n}\n\nexport const isUserAnonymous = (user: { is_anonymous?: boolean } | null) => {\n  return user?.is_anonymous === true;\n};\n\n/** Fetch the current Supabase user, or null when unauthenticated/unconfigured. */\nexport async function getCurrentUser() {\n  const supabase = getSupabaseClient();\n  if (!supabase) return null;\n  const {\n    data: { user },\n  } = await supabase.auth.getUser();\n  return user;\n}\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/proprietary/auth/supabase/supabaseClient.ts#L31-L67","documentation":"Thrown by signInAnonymously() in the proprietary Supabase client wrapper when the shared module-level client is still null. The client is created lazily via configureSupabase(); until that runs, getSupabaseClient() returns null by design so hosts that never need Supabase (e.g. the portal in Spring mode) don't pull it into the session. Anonymous sign-in is only valid against a live Supabase backend, so the guard fails fast instead of dereferencing null.","triggerScenarios":"Calling signInAnonymously() before any configureSupabase({url,key}) call; calling it in a Spring-auth build where the unified auth provider was never wired to Supabase; calling it during SSR or before the auth bootstrap effect has run.","commonSituations":"Missing VITE_SUPABASE_URL / VITE_SUPABASE_ANON_KEY env vars so the bootstrap skips configureSupabase; running the proprietary build in a flavor (core/desktop) that doesn't initialize the Supabase path; a race where a guest-login button renders before the auth provider's init effect.","solutions":["Call configureSupabase({url, key}) during app startup (typically in the unified auth provider) before any guest/anonymous sign-in is possible.","Verify VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set in the active .env layer (frontend/editor/.env plus the mode-specific file) and not just in a .local you forgot to commit for CI.","Gate the anonymous-sign-in UI on a flag that is only true once Supabase is confirmed configured (e.g. isSupabaseConfigured), so the button can't be clicked in Spring mode.","If the portal is intentionally Spring-only, remove the code path or branch it so signInAnonymously is never reached."],"exampleFix":"// before\nawait signInAnonymously(); // throws if never configured\n\n// after\nconst client = getSupabaseClient();\nif (!client) {\n  throw new Error(\"Guest sign-in requires Supabase; enable it in Settings > Auth.\");\n}\nawait signInAnonymously();","handlingStrategy":"validation","validationCode":"import { getSupabaseClient } from \"@app/auth/supabase/supabaseClient\";\n\nconst client = getSupabaseClient();\nif (!client) {\n  // don't call signInAnonymously; show 'guest sign-in unavailable'\n}","typeGuard":"export function canSignInAnonymously(): boolean {\n  return getSupabaseClient() !== null;\n}","tryCatchPattern":"try {\n  await signInAnonymously();\n} catch (e) {\n  if (/not configured/i.test(e instanceof Error ? e.message : \"\")) {\n    showGuestSignInUnavailable();\n  } else {\n    throw e;\n  }\n}","preventionTips":["Call configureSupabase once during app bootstrap and assert getSupabaseClient() is non-null before rendering auth-dependent UI.","Gate the anonymous-sign-in button on isSupabaseConfigured so it can't be clicked in Spring mode.","Treat VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY as required for the proprietary build and fail the build if missing."],"tags":["supabase","auth","configuration","proprietary","typescript"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}