Skip to content

Snapshot marker name silently truncates past 63 bytes #148

Description

@lukashes

markerName() (src/source/postgres/replication_protocol.zig) appends _snapshotting (13 chars) to the slot name. slot_name is validated up to MAX_IDENTIFIER_LEN = 63 (src/config/config.zig), so any slot name over 50 chars produces a marker name over Postgres' 63-byte identifier limit.

This is not broken today. Verified on the dev container (PG17):

CREATE PUBLICATION <64 chars>  -> NOTICE: identifier ... will be truncated, CREATE PUBLICATION
SELECT ... WHERE pubname = '<64 chars>'  -> 1 row
DROP PUBLICATION IF EXISTS <64 chars>    -> DROP PUBLICATION

It works because pg_publication.pubname has type name: the literal in objectExists's comparison is coerced to name and truncated to 63 bytes exactly like CREATE PUBLICATION truncates it, so both sides match. Create, probe, and drop stay consistent.

Two things are still worth closing:

  • Two slot names that share their first 50 characters collapse onto the same truncated marker. Each pipeline would then read the other's marker as its own, which is the state the marker is meant to make unambiguous.
  • The correctness above rests on implicit text -> name coercion. Nothing in the code says so, and a future rewrite of the probe (a LIKE, a ::text cast, an ORM) would silently break interrupted-snapshot recovery with no test to catch it.

Ask: validate the derived marker name against 63 bytes at config time (rejecting the over-long slot name with a clear message), or truncate it in markerName the way Postgres does. Either way, add a test that pins the behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    size/SRelative effort: small

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions