-
Notifications
You must be signed in to change notification settings - Fork 606
Description
Bug Report
Describe the bug
Single-column .eq() filters on certain tables silently return empty arrays when running inside Vercel Serverless Functions. The exact same query works correctly via the Supabase REST API (curl) and in local development (next dev).
To Reproduce
Table schema:
CREATE TABLE check_ins (
id BIGSERIAL PRIMARY KEY,
epoch_day INTEGER NOT NULL,
wallet TEXT NOT NULL,
weight INTEGER NOT NULL DEFAULT 1,
checked_in_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(epoch_day, wallet)
);
CREATE INDEX idx_checkins_wallet ON check_ins(wallet);
ALTER TABLE check_ins ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Public read check_ins" ON check_ins FOR SELECT USING (true);Code that fails on Vercel (returns empty data):
const { data, error } = await supabase
.from('check_ins')
.select('epoch_day, weight, wallet')
.eq('wallet', walletAddress);
// data = [] on Vercel, correct results locally and via REST APISame query via REST API works:
curl "https://<project>.supabase.co/rest/v1/check_ins?wallet=eq.<wallet>&select=epoch_day,weight,wallet" \
-H "apikey: <service_key>" -H "Authorization: Bearer <service_key>"
# Returns correct rowsWorkaround that works everywhere:
const { data: all } = await supabase
.from('check_ins')
.select('epoch_day, weight, wallet')
.limit(10000);
const rows = (all || []).filter((r) => r.wallet === walletAddress);Additional observations
-
.eq()with a second filter works fine:.eq('epoch_day', X).eq('wallet', wallet)returns correct results. The issue only appears when.eq('wallet', wallet)is the sole filter. -
.in().gt()chained filters also fail:.in('epoch_day', [...]).gt('total_weight', 0)returns empty despite matching rows existing. Splitting into.in()only and filtering.gt()in JS resolves it. -
.select('*', { count: 'exact', head: true })with.eq()also returns 0 despite rows existing. -
.select().limit(N)without any.eq()filter returns correct results, confirming the data is accessible. -
The same client instance (service role key, same
createClientcall) works for.eq()on other tables. -
Issue reproduces with both
anonkey andservice_rolekey. -
RLS is enabled with a permissive
FOR SELECT USING (true)policy.
Expected behavior
.eq('wallet', walletAddress) should return the same rows as the equivalent REST API query.
Environment
@supabase/supabase-js: ^2.49.1- Runtime: Vercel Serverless Functions (Node.js 22.x)
- Framework: Next.js 14 (App Router, force-dynamic)
- Supabase: Hosted (free tier)
- Region: US East
Possible causes
- PostgREST query planner behaving differently with single-filter vs multi-filter queries
- Connection pooling or stale schema cache in serverless cold starts
- RLS policy evaluation interacting with the query in unexpected ways
- supabase-js query builder serializing the filter differently than expected