risingwavelabs/risingwave · error · SinkError::Config

Postgres sink does not support target table

Error message

Postgres sink does not support target table "{}"."{}" with foreign key constraints. Please remove foreign key constraints from the target table or choose a different sink table.

What it means

`ensure_no_foreign_key_with_client` queries the target Postgres database for foreign key constraints on the sink target table and refuses to proceed if any exist, because RisingWave cannot maintain referential constraints on rows it upserts. The error names the offending `schema.table`.

Solutions

  1. Drop the foreign key constraints on the target table before creating the sink: `ALTER TABLE schema.table DROP CONSTRAINT <fk_name>;`
  2. Sink into a different, constraint-free staging table instead
  3. Sink into a fresh table dedicated to RisingWave output without FKs

Example fix

// before
ALTER TABLE public.target ADD CONSTRAINT fk_parent FOREIGN KEY (pid) REFERENCES parents(id);
// after (remove FK so the sink can target the table)
ALTER TABLE public.target DROP CONSTRAINT fk_parent;
Defensive patterns

Strategy: validation

Validate before calling

-- run against the target database before creating the sink
SELECT COUNT(*) > 0 AS has_fk
FROM information_schema.table_constraints tc
JOIN information_schema.constraint_column_usage ccu
  ON tc.constraint_name = ccu.constraint_name
WHERE tc.table_schema = $1 AND tc.table_name = $2
  AND tc.constraint_type = 'FOREIGN KEY';
-- expect 0 rows / false

Try / catch

match ensure_no_foreign_key(&client, &schema, &table).await {
    Ok(()) => proceed(),
    Err(e) => plan_fk_removal(&schema, &table, e),
}

Prevention

When it happens

Trigger: Creating a Postgres sink with `type='upsert'` (or sink type requiring direct table writes) where the destination table `schema.table` has FK constraints referencing or referenced by other tables; raised from `ensure_no_foreign_key` during writer `new`/validation.

Common situations: Sinking into an existing Postgres table that is part of a normalized relational schema with FKs; DBA-managed schemas where FKs are standard practice.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/ef56157028206f5d. Report an issue: GitHub.

Appendix: source

Thrown at src/connector/src/sink/postgres.rs:140

    )
    .await?;

    ensure_no_foreign_key_with_client(&client, &config.schema, &config.table).await
}

async fn ensure_no_foreign_key_with_client(
    client: &tokio_postgres::Client,
    schema: &str,
    table: &str,
) -> Result<()> {
    let has_foreign_key = client
        .query_one(CHECK_FOREIGN_KEY_SQL, &[&schema, &table])
        .await
        .context("failed to check foreign key constraints")?
        .get::<_, bool>(0);

    if has_foreign_key {
        return Err(SinkError::Config(anyhow!(
            "Postgres sink does not support target table \"{}\".\"{}\" with foreign key constraints. Please remove foreign key constraints from the target table or choose a different sink table.",
            schema,
            table,
        )));
    }

    Ok(())
}

impl PostgresConfig {
    pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {
        let config =
            serde_json::from_value::<PostgresConfig>(serde_json::to_value(properties).unwrap())
                .map_err(|e| SinkError::Config(anyhow!(e)))?;
        if config.r#type != SINK_TYPE_APPEND_ONLY && config.r#type != SINK_TYPE_UPSERT {
            return Err(SinkError::Config(anyhow!(
                "`{}` must be {}, or {}",
                SINK_TYPE_OPTION,

View on GitHub (pinned to 6469eb736d)