windmill-labs/windmill · error

Unexpected NULL `schema_name` in publication entry (pubname:

Error message

Unexpected NULL `schema_name` in publication entry (pubname: `{}`). This should never happen unless PostgreSQL internals are corrupted.

What it means

get_tracked_relations reads publication relation rows from PostgreSQL (pg_publication_tables-style query). The schema_name column is nullable in the row type, but a NULL here would mean corrupt PostgreSQL catalog internals, so the code fails loudly with this error instead of proceeding.

Source

Thrown at backend/windmill-trigger-postgres/src/handler.rs:934

            pubname = $1;
        "#
    };

    let rows = pg_connection
        .query(query, &[&publication_name])
        .await
        .map_err(to_anyhow)?;

    let mut table_to_track: HashMap<String, Relations> = HashMap::new();

    for row in rows {
        let schema_name: Option<String> = row.get("schema_name");
        let table_name: Option<String> = row.get("table_name");
        let columns: Option<Vec<String>> = row.get("columns");
        let where_clause: Option<String> = row.get("where_clause");

        let schema_name = schema_name.ok_or_else::<Error, _>(|| {
            anyhow::anyhow!(
                "Unexpected NULL `schema_name` in publication entry (pubname: `{}`). This should never happen unless PostgreSQL internals are corrupted.",
                publication_name,
            )
            .into()
        })?;

        let table_name = table_name.ok_or_else::<Error, _>(|| {
            anyhow::anyhow!(
                "Unexpected NULL `table_name` for schema `{}` in publication `{}`. This should never happen unless PostgreSQL internals are corrupted.",
                schema_name,
                publication_name,
            )
            .into()
        })?;

        let entry = table_to_track.entry(schema_name.clone());
        let table_to_track_item = TableToTrack::new(table_name, where_clause, columns);

View on GitHub (pinned to e474e8803c)

Solutions

  1. Verify catalog integrity: dump pg_publication_tables on the same DB and inspect the rows
  2. Check for pg_upgrade/restore issues; reindex system catalogs or restore from a clean backup
  3. Confirm the connection targets a real PostgreSQL server, not a shim rewriting catalog queries
  4. Compare your PostgreSQL version against the versions Windmill's postgres trigger supports
  5. Report to Windmill if a supported Postgres version reproduces it on a healthy database
Defensive patterns

Strategy: try-catch

Validate before calling

-- verify publication catalog integrity before configuring the trigger
SELECT pubname, schemaname, tablename
FROM pg_publication_tables
WHERE pubname = 'my_publication' AND schemaname IS NULL;
-- must return zero rows

Try / catch

match get_publication_info(...).await {
    Err(e) if e.to_string().contains("Unexpected NULL `schema_name`") => {
        anyhow::bail!("Postgres catalog looks corrupted; refusing to sync publication state")
    }
    other => other,
}

Prevention

When it happens

Trigger: Running the publication-info query against a PostgreSQL instance whose catalog returns NULL schema_name for an entry in the given publication — per PostgreSQL this should never occur in a healthy database.

Common situations: A corrupted system catalog after a botched upgrade/restore; querying via a proxy/federated layer that mangles catalog columns; a Postgres version with divergent catalog behavior read with mismatched column aliases.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/0665444668b77b2e. Report an issue: GitHub.