February 26, 2026·5 min read·engineeringpostgresqlreplicationmaintenance

PostgreSQL 18.3 repairs the February update and a catalog mistake

The out-of-cycle update fixes standby replay and text processing regressions. Existing PostgreSQL 18 clusters also need attention to the volatility of two JSON functions.

PostgreSQL's February 26 update addresses regressions that appeared after the previous maintenance release. The announcement covers PostgreSQL 18.3, 17.9, 16.13, 15.17 and 14.22. For operators, the most immediate issue is a standby that can stop replaying WAL after a minor-version update. There is also a separate PostgreSQL 18 catalog correction that replacing the binaries does not apply to an existing cluster.

I still default to PostgreSQL for relational systems after decades of production use. Part of that preference comes from being able to examine the database's behavior and the documented exceptions to its normal rules. This update is worth reading closely because the release notes identify different kinds of corrective work. A replay failure needs a binary fix, while incorrectly stored function metadata may need a database-by-database catalog update.

A standby can encounter an older primary's WAL

The 18.3 release notes describe a failure after replaying a multixid truncation record generated by an older minor version. The erroneous logic concerned how previous versions handled multixid wraparound. A typical affected configuration has a standby on the latest minor version consuming WAL from a primary still on an older version. The resulting error can say that PostgreSQL could not access the status of a transaction.

This makes the upgrade sequence relevant to diagnosis. A standby can encounter the fault during the interval when its binaries are newer than the primary's binaries. The release notes explicitly describe that mixed-version case, so I would record both servers' minor versions when investigating this error. Looking only at the version of the server that stopped would omit part of the documented trigger.

The notes call this a replay failure. They do not say that the message proves the primary has lost committed data or that the operator should discard the standby. I would avoid making either inference from the wording of the error. The first useful action is to compare the observed topology and version history with the stated failure case, then apply the corrected maintenance release through the installation's normal upgrade procedure.

For validation, I would want evidence that the affected standby is replaying WAL again. A server accepting connections would not answer the specific question raised by this bug. The relevant behavior is its ability to consume the primary's WAL, particularly if the primary still has the older minor version during a staged rollout.

Security fixes exposed text processing regressions

The update also corrects behavior introduced by the fixes for CVE-2026-2006 and CVE-2026-2007. In the first regression, substring() on toasted data could reject valid input with an incomplete-character error. The announcement describes the visible symptom as an invalid-byte-sequence error for non-ASCII text values coming from a database column.

That distinction matters when constructing a regression test. I would preserve the original failing query and its stored value. Replacing the column reference with a short literal might remove the data representation involved in the documented fault. The release notes are specific about toasted data, so a test should retain that condition if it is present in the affected application.

The pg_trgm correction has a different mechanism. When an input contained more trigrams than the initial allocation expected, the implementation could expand a bounds array without returning its modified pointer to the caller. The result could be incorrect output from strict_word_similarity() and related functions, or occasionally a crash. The notes say the faulty path requires an input that becomes longer when converted to lower case.

The known instances involve an ICU locale with certain single-byte encodings. That limits what the release notes establish about the trigger. I would check the actual encoding and locale of an affected database before assuming that every use of pg_trgm has the same exposure. At the same time, a narrow known trigger is not a reason to leave a documented correctness fix unapplied when planning the maintenance update.

Function metadata survives a binary replacement

The JSON change deserves a separate upgrade task. Refactoring in PostgreSQL 18 accidentally marked json_strip_nulls() and jsonb_strip_nulls() as stable instead of immutable. The release notes say this prevents their use in index expressions and can cause unnecessary repeated evaluation in queries. The correction restores their previous classification.

Newly initialized clusters receive the corrected marking, including clusters upgraded to 18.3 or later with pg_upgrade. Existing clusters created with 18.0 through 18.2 retain the wrong catalog entries. The release notes recommend the following manual catalog update for affected usage, executed as a PostgreSQL superuser in each affected database.

UPDATE pg_catalog.pg_proc
SET provolatile = 'i'
WHERE oid IN ('3261','3262');

This is the release's specific repair statement. I would use it only under the conditions described by these release notes, with the same care given to any direct catalog modification. The required scope includes template0 and template1, so databases created later inherit the correct marking. Fixing only the application's current database would leave that future-database behavior unresolved.

The difference between new and existing clusters also affects testing. A test installation freshly initialized with 18.3 can have correct metadata even when an existing production installation still has the old values. I would therefore verify the upgrade on a representation of the existing cluster. A successful test against a newly created database does not establish that the catalog repair has reached every database that needs it.

Define completion by the affected behavior

The announcement says these minor releases are cumulative and do not require dumping and reloading the database or using pg_upgrade. The normal binary update requires shutting PostgreSQL down and replacing its binaries. Operators skipping previous updates should also read their release notes for additional post-update actions. The JSON correction is a concrete example of why the installed version alone cannot describe all completed maintenance work.

I would track the catalog repair separately from binary deployment, then retain tests for any replay or text-processing failure that prompted the upgrade. The remaining fixes include wrong query output involving a LATERAL UNION ALL subquery and a crash in hstore binary input containing duplicate keys. Those details reinforce my preference for validating the queries and data paths that an installation actually depends on, with the catalog correction included in the recorded upgrade result.