neondatabase/neon · error

Neon RMGR has no known compatibility with PostgreSQL version

Error message

Neon RMGR has no known compatibility with PostgreSQL version {}

What it means

`decode_neonmgr_record` only knows how to decode Neon-RMGR records for PostgreSQL 16 and 17; for PG14 and PG15 it bails unconditionally because Neon's postgres fork never emitted RM_NEON records on those versions. Seeing this error means an RM_NEON_ID record was decoded against a pg_version of PG14/PG15 — an inconsistent WAL/version combination.

Source

Thrown at libs/wal_decoder/src/decoder.rs:576

                                size_of::<u16>() * xlrec.ntuples as usize
                            };
                        assert_eq!(offset_array_len, buf.remaining());

                        if (xlrec.flags & pg_constants::XLH_INSERT_ALL_VISIBLE_CLEARED) != 0 {
                            new_heap_blkno = Some(decoded.blocks[0].blkno);
                        }
                    }
                    pg_constants::XLOG_NEON_HEAP_LOCK => {
                        let xlrec = v17::rm_neon::XlNeonHeapLock::decode(buf);
                        if (xlrec.flags & pg_constants::XLH_LOCK_ALL_FROZEN_CLEARED) != 0 {
                            old_heap_blkno = Some(decoded.blocks[0].blkno);
                            flags = pg_constants::VISIBILITYMAP_ALL_FROZEN;
                        }
                    }
                    info => anyhow::bail!("Unknown WAL record type for Neon RMGR: {}", info),
                }
            }
            PgMajorVersion::PG15 | PgMajorVersion::PG14 => anyhow::bail!(
                "Neon RMGR has no known compatibility with PostgreSQL version {}",
                pg_version
            ),
        }

        if new_heap_blkno.is_some() || old_heap_blkno.is_some() {
            let vm_rel = RelTag {
                forknum: VISIBILITYMAP_FORKNUM,
                spcnode: decoded.blocks[0].rnode_spcnode,
                dbnode: decoded.blocks[0].rnode_dbnode,
                relnode: decoded.blocks[0].rnode_relnode,
            };

            Ok(Some(MetadataRecord::Neonrmgr(NeonrmgrRecord::ClearVmBits(
                ClearVmBits {
                    new_heap_blkno,
                    old_heap_blkno,
                    vm_rel,

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Verify the pg_version passed to the decoder against the timeline metadata of the WAL source
  2. If the WAL genuinely contains Neon RMGR records, the source must be PG16/PG17 — fix version detection
  3. Restart ingestion from a point where version and WAL stream agree
  4. Check how pg_version is derived (timeline info vs. config) and correct the source
Defensive patterns

Strategy: validation

Validate before calling

if decoded.xl_rmid == pg_constants::RM_NEON_ID
    && matches!(pg_version, PgMajorVersion::PG14 | PgMajorVersion::PG15)
{
    anyhow::bail!("pg_version {pg_version} cannot produce Neon RMGR records; check version detection");
}

Type guard

fn neon_rmgr_supported(pg_version: PgMajorVersion) -> bool {
    matches!(pg_version, PgMajorVersion::PG16 | PgMajorVersion::PG17)
}

Prevention

When it happens

Trigger: Decoding WAL that contains RM_NEON_ID records while `pg_version` says PG14 or PG15 — almost always the version argument not matching the cluster that actually wrote the WAL.

Common situations: Wrong pg_version passed to WalDecoder after a major-version upgrade mapping bug; version detection reading stale timeline metadata; experimental Neon builds backporting the Neon RMGR to older branches.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/72f1a3f0e7d65c58. Report an issue: GitHub.