Lewati ke konten utama

Error Log

Running log of significant bugs, incidents, and fixes in the Seken platform. Updated after every non-trivial incident. Most recent entry first.

For incident response procedures, see Maintenance Guide →. For the post-incident review template, see the same page.


Format​

## YYYY-MM-DD — Short description of incident
**Severity:** Low / Medium / High / Critical
**Affected:** What broke
**Cause:** Root cause
**Fix:** What was done to resolve it
**Prevention:** How to avoid in future

2026-05-03, search_terms table absent from PostgREST schema cache (PS-137)​

Severity: High Affected: Backend, SupabaseSearchTermRepository (findTrending, findMatching, upsertTerm) Cause: public.search_terms was defined in migration 20260425000003_kv_migration_tables.sql inside a 26 KB batch that did not fully apply to production. PostgREST had no schema knowledge of the table, causing every call to findTrending, findMatching, and upsertTerm to throw "Could not find the table 'public.search_terms' in the schema cache" (Sentry issue #117067953, 3 events, 3 users). Trending search suggestions on buyer discovery and search screens were broken in production. supabase/config.toml already had public in [api].schemas, that was not the issue. Fix: New idempotent migration 20260503114936_ensure_search_terms_postgrest.sql, CREATE TABLE IF NOT EXISTS public.search_terms (term TEXT PRIMARY KEY, search_count INTEGER DEFAULT 0, last_searched_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now()); RLS: SELECT open to anon + authenticated, INSERT/UPDATE to service_role only; SELECT pg_notify('pgrst', 'reload schema') forces immediate PostgREST cache reload. SearchTermRow duplicate interface in SupabaseSearchTermRepository.ts removed; canonical RowSearchTerm added to row-types.ts and re-exported for backward compat. Branch: fix/ps-137-search-terms-postgrest. Prevention: Any table created as part of a large batch migration should be validated in staging before production deploy. When 20260425000003 was applied, each table in the batch should have been confirmed via SELECT * FROM information_schema.tables WHERE table_name = 'search_terms'. Add this to the migration validation checklist.


2026-05-03, Boost lookups querying dropped table (PS-136)​

Severity: High Affected: Backend, routes-listings.tsx (listing feed ranking), routes-growth.tsx (admin boost endpoints, GET /api/check-boost/:sellerId) Cause: getByPrefixAll("boost:") in shared-infra.tsx still queried kv_store_e10b1b67, a table dropped during the Phase 14 KV-to-relational migration on 2026-04-16. The boost:{listingId} data was migrated to the promotions table (promo_type = 'boost'), but the three callers in routes-listings.tsx and routes-growth.tsx were never updated. Sentry error #117067954, 4 users. Boost lookups silently returned empty results, the listing feed +60 ranking bonus for boosted sellers was non-functional, and the seller dashboard boost check always returned has_boost: false. Fix: All three getByPrefixAll("boost:") callers rewritten to query promotions via SupabasePromotionRepository. New methods: findAllBoostsRaw() and findActiveBoostsBySellerId(). Branch: fix/PS-136-boost-kv-stale-prefix-query. Prevention: After any KV-to-relational migration, grep for the retired KV prefix across all route files before closing the ticket. kv_store_e10b1b67 should now return zero hits, add this to the migration checklist.


2026-05-03, app_settings table absent from production (PS-135)​

Severity: High Affected: Backend, SupabaseAppSettingsRepository (all callers of findByKey) Cause: Migration 20260425000003_kv_migration_tables.sql included the public.app_settings DDL inside a 26 KB batch migration that did not fully apply to production. PostgREST had no schema knowledge of the table, causing every SupabaseAppSettingsRepository.findByKey call to throw "Could not find the table 'public.app_settings' in the schema cache" (Sentry issue #117090178, 2 events, 2 users). Fix: New idempotent migration 20260503000001_ensure_app_settings_table.sql, CREATE TABLE IF NOT EXISTS with all columns (key, value JSONB, updated_by, deleted_at, updated_at, created_at); ADD COLUMN IF NOT EXISTS guards for environments where the table partially existed; service_role-only RLS policy; seeds 4 known config keys (global, active_incident, feature_flags, pulse_weights) with ON CONFLICT DO NOTHING; NOTIFY pgrst, 'reload schema' forces PostgREST to pick up the table immediately without a function restart. KVAppSettings stale type stub in row-types.ts replaced with RowAppSettings interface matching the table columns exactly. Branch: fix/ps-135-app-settings-schema. Prevention: Large batch migrations should be validated in staging before production deploy. When a migration file is very large, audit its sections individually. Any new repository that queries a table should have a smoke test that verifies the table exists in the schema cache.


2026-05-02, Edge function catch blocks invisible to Sentry (PS-133)​

Severity: High Affected: Backend, all Supabase Edge Functions (supabase/functions/server/) Cause: 746 explicitly-caught errors were never sent to Sentry. The only captureException() call was inside the top-level app.onError() in index.tsx, which only fires for uncaught exceptions. Every database failure, Xendit/Biteship/OpenAI/Resend adapter error, auth failure, and business logic exception caught in a try/catch block was being swallowed, logged via slog()/console.warn() but completely invisible in the Sentry dashboard. This meant production monitoring had a blind spot covering the vast majority of error paths. Fix: Added captureException() to 698 catch blocks across 82 files. New infrastructure/observability/errorReporter.ts singleton wired by container.ts at cold-start via setErrorReporter(), avoids circular imports so repositories and adapters (which are themselves imported by container.ts) can call captureException without creating a dependency loop. Revenue-risk paths (orders, Xendit, finance, payment/order repositories) instrumented first. 28 intentionally non-fatal blocks (e.g. cache misses, optional enrichment) documented inline and skipped. Post-instrumentation syntax scan found and fixed 6 files with automated-insertion bugs (import injected inside import type {} block; type annotation written inside call expression) before merge. Branch: fix/PS-133-sentry-silent-catch-blocks. Prevention: Any new catch block in supabase/functions/server/ should call captureException() unless the error is intentionally non-fatal, document the skip reason with a comment. After any large automated code-modification pass, run a syntax scan before committing.


2026-05-02, Flutter AI listing fields silently dropped (PS-132)​

Severity: Medium Affected: Mobile, listing creation AI categorization Cause: _uploadAndRunAiCategorization() in create_listing_screen.dart only assigned 7 of 20+ fields returned by /ai/categorize. style, sub_category, vibe_tags, original_price, and the confidence warning toast were all silently discarded. React's CreateListingFlow.tsx maps all of them. Flutter sellers had been creating listings with incomplete metadata since the AI pipeline launched. Fix: Added state variables for all 4 missing fields with proper disposal. All 4 assigned inside setState. Confidence toast (amber snackbar) fires when score is below 30%. All 4 fields included in _submit() payload (conditionally for sub_category, vibe_tags, original_price). UI widgets added to _buildDetailsStep(): original price field, style dropdown, sub-category text field, vibe tags chip row. Branch: fix/PS-132-flutter-ai-missing-fields. Prevention: When adding new fields to /ai/categorize backend response, update both React CreateListingFlow.tsx and Flutter create_listing_screen.dart in the same PR. Check the analysis [[wiki/analyses/ai-image-analyzer-flutter-react-gap-2026-05-02]] when modifying the AI pipeline.


2026-05-02, Flutter AI categorization silently assigned wrong gender (PS-131)​

Severity: Medium Affected: Mobile, listing creation AI categorization Cause: create_listing_screen.dart compared result['gender_id'] against 'M'/'F'. The backend returns a normalized gender field with values 'men'/'women'. The comparison never matched, so every AI-scanned listing silently defaulted to 'women' regardless of what GPT-4o mini detected. Fix: Read result['gender'] directly; manual gender_id translation removed. description_id left unchanged, the backend still emits that key name. Branch: fix/PS-131-flutter-ai-response-field-names. Prevention: When the backend AI response schema changes, update the Flutter field mapping in the same PR. Cross-reference against routes-ai-vision.tsx response object to verify key names.


2026-03-19, Initial error log created​

Severity: Low Affected: Documentation Cause: Developer docs section did not exist, no structured place to record incidents. Fix: Created docs/developer/ section including this error log. Prevention: All future incidents should be documented here within 24 hours of resolution.


Add new entries above this line, most recent first.