refinedev/refine · warning

[refine/supabase] Multiple filters are not supported for Sup

Error message

[refine/supabase] Multiple filters are not supported for Supabase Realtime subscriptions. Using only the first filter: "${mapped[0]}".

What it means

Warned by the Supabase live provider's filter mapper. Supabase Realtime `postgres_changes` subscriptions accept a single filter string per event; when the refine filters map to more than one condition, only the first is applied and the rest are silently dropped (with this warning). The comment notes that comma-joining filters produces an invalid payload and can break the subscription entirely.

Source

Thrown at packages/supabase/src/liveProvider/index.ts:74

        const mapped = filters
          .map((filter: CrudFilter): string | undefined => {
            if ("field" in filter) {
              return `${filter.field}=${mapOperator(filter.operator)}.${
                filter.value
              }`;
            }
            return;
          })
          .filter((x): x is string => Boolean(x));

        if (mapped.length === 0) return;

        if (mapped.length > 1) {
          // Supabase Realtime currently supports only a single `filter` string
          // for postgres_changes. Joining multiple filters with commas
          // results in an invalid payload and may break the subscription.
          console.warn(
            `[refine/supabase] Multiple filters are not supported for Supabase Realtime subscriptions. Using only the first filter: "${mapped[0]}".`,
          );
        }

        return mapped[0];
      };

      const events = types
        .map((x) => supabaseTypes[x])
        .sort((a, b) => a.localeCompare(b));

      const filter = mapFilter(params?.filters);

      const ch = `${channel}:${events.join("|")}${filter ? `:${filter}` : ""}`;

      let client = supabaseClient.channel(ch);

      for (let i = 0; i < events.length; i++) {

View on GitHub (pinned to 779d52a20e)

Solutions

  1. Reduce to a single realtime-relevant filter column, or accept that only the first is used for subscriptions
  2. Move compound filtering client-side: subscribe broadly (single filter) and filter incoming events in `onLiveEvent`/your own logic
  3. Use a database view or a computed column so one filter column captures the condition, and point the resource/filter at it

Example fix

// before
const { data } = useTable({
  resource: 'orders',
  filters: { permanent: [
    { field: 'status', operator: 'eq', value: 'open' },
    { field: 'storeId', operator: 'eq', value: 5 },
  ]},
});
// after — single filter for realtime; verify remaining conditions client-side
const { data } = useTable({
  resource: 'orders',
  filters: { permanent: [
    { field: 'status', operator: 'eq', value: 'open' },
  ]},
});
Defensive patterns

Strategy: validation

Validate before calling

const realtimeFilters = filters.map(mapFilter).filter(Boolean);
if (realtimeFilters.length > 1) {
  console.warn('Only the first Supabase realtime filter will be applied');
}

Type guard

const isSingleRealtimeFilter = (mapped: (string | undefined)[]) =>
  mapped.filter(Boolean).length <= 1;

Prevention

When it happens

Trigger: Subscribing to a resource via useList/useTable live hooks (liveProvider: supabase) where `filters`/`permanentFilter` produce multiple mapped realtime filters — e.g. filtering on two different columns at once.

Common situations: List pages with permanentFilter on one column plus a user-applied filter on another; relying on realtime updates to respect all active table filters.

Related errors


AI-assisted analysis of refinedev/refine@779d52a20e (2026-08-27). Data as JSON: /api/errors/92eddbab321ad67a. Report an issue: GitHub.