n8n-io/n8n · error

Supabase delete failed: ${error.message}

Error message

Supabase delete failed: ${error.message}

What it means

Thrown by SupabaseVectorStore.delete when the PostgREST delete call returns a non-null error. Root causes, named in the appended message, are usually RLS denying DELETE, a missing table, an auth/connection failure, or (rarely) a constraint that blocks the delete. Empty id lists short-circuit before this call, so this only fires for a real delete attempt.

Source

Thrown at packages/@n8n/agents/src/vector-stores/supabase.ts:149

			query_embedding: vector,
		});
		const filtered =
			opts.filter && opts.filter.conditions.length > 0
				? applySupabaseFilter(rpcCall, opts.filter)
				: rpcCall;

		const { data, error } = await filtered.limit(opts.topK);
		if (error) throw new Error(`Supabase query failed: ${error.message}`);

		return (data ?? []).map(toQueryResult);
	}

	async delete({ ids }: { ids: string[] }): Promise<void> {
		if (ids.length === 0) return;

		const client = await this.getClient();
		const { error } = await client.from(this.tableName).delete().in('id', ids);
		if (error) throw new Error(`Supabase delete failed: ${error.message}`);
	}

	close(): void {
		this.client = undefined;
	}

	private async getClient(): Promise<SupabaseClient> {
		if (!this.client) {
			const { createClient } = await import('@supabase/supabase-js');
			this.client = createClient(this.constructorOptions.url, this.constructorOptions.apiKey);
		}
		return this.client;
	}
}

function toQueryResult(row: SupabaseMatchRow): VectorQueryResult {
	return {
		id: String(row.id),

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the appended message to classify (RLS vs missing relation vs constraint).
  2. For RLS, use the service role key for trusted deletes or add a DELETE policy.
  3. Confirm the table name is correct and the table exists.
  4. For FK/constraint blocks, delete dependent rows first or adjust the constraint.
  5. Retry transient/network errors.

Example fix

// before — anon key, RLS blocks delete
new SupabaseVectorStore('docs', {
  url, apiKey: process.env.SUPABASE_ANON_KEY, tableName: 'docs',
});

// after — service role key, or add a DELETE policy
new SupabaseVectorStore('docs', {
  url, apiKey: process.env.SUPABASE_SERVICE_ROLE_KEY, tableName: 'docs',
});
Defensive patterns

Strategy: retry

Validate before calling

function assertSupabaseDeletable(opts: { url: string; apiKey: string; tableName: string }): void {
  if (!opts.apiKey) throw new Error('Supabase apiKey missing (service role needed for deletes)');
  if (!opts.tableName) throw new Error('Supabase tableName missing');
  if (!/^https?:\/\/.+/.test(opts.url)) throw new Error('Supabase url missing/invalid');
}

assertSupabaseDeletable(opts);

Try / catch

async function deleteWithRetry(store: SupabaseVectorStore, ids: string[], attempts = 3) {
  if (ids.length === 0) return;
  for (let i = 0; i < attempts; i++) {
    try {
      await store.deleteDocuments(ids);
      return;
    } catch (err) {
      const msg = err instanceof Error ? err.message : '';
      const transient = /network|timeout|fetch|ECONN|503|504|paused/i.test(msg);
      if (!transient || i === attempts - 1) throw err;
      await new Promise((r) => setTimeout(r, 2 ** i * 200));
    }
  }
}

Prevention

When it happens

Trigger: RLS policy without a DELETE grant for the api key's role; tableName pointing at a non-existent table; service key wrong/expired; Supabase project paused; foreign-key ON DELETE RESTRICT blocking removal (surfaced through PostgREST).

Common situations: Anon key used for deletes (RLS blocks); RLS enabled but no DELETE policy; schema migration renaming the table; FK constraint preventing deletion of referenced rows.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/5b93f8dd6471d424. Report an issue: GitHub.