PostgreSQL Troubleshooting
Common issues
library "wal2json" may not be used as an output plugin
Symptom: every entity of a pipeline that sources from PostgreSQL goes into error and restarts in a loop, producing a burst of notifications. The agent logs report:
SQL Error: Code 0, State 42501, Message ERROR: library "wal2json" may not be used as an output plugin
The exception class is org.postgresql.util.PSQLException and the server adds its own hint:
HINT: If it is safe for all REPLICATION users to use this library as an output plugin,
add it to "output_plugin_libraries" and reload the server configuration.
|
SQLSTATE |
Cause: the PostgreSQL minor releases 18.6, 17.11, 16.15, 15.19 and 14.24, published on 13 August 2026, fix CVE-2026-6471. Before the fix, a user with the REPLICATION privilege could make the server load an arbitrary library as a logical decoding output plugin, which meant arbitrary code execution as the operating system user running the server.
The fix introduces the output_plugin_libraries parameter, whose default value is 'pgoutput, test_decoding', the two output plugins shipped with the standard PostgreSQL distribution. It is a pure allowlist: there is no wildcard value, and the restriction applies to every user, superusers included.
Gluesync reads changes from PostgreSQL through the wal2json output plugin, which on an upgraded server is therefore no longer authorised by default. See Replication configuration parameters in the PostgreSQL documentation for the parameter reference.
|
The refusal does not appear when the PostgreSQL packages are upgraded. It appears at the first restart of the PostgreSQL service after the upgrade, because the replication stream that is already open survives the package installation. On distributions that apply security updates automatically (for example |
The PostgreSQL documentation also requires the plugin name sent by the client to match an entry of the list exactly, "without variations in case or path structure". The entry must therefore be exactly wal2json.
Impact on data
The consequences differ depending on whether the entity was already replicating before the upgrade.
-
Entities already in CDC before the upgrade: the replication slot exists and stops advancing, so PostgreSQL keeps retaining the WAL segments the slot still needs. No change is lost, and once the parameter is fixed CDC resumes from the point where it stopped.
-
Pipelines created after the upgrade: the replication slot is never created, so there is no WAL retention and the changes that happen in the meantime cannot be recovered through CDC. A snapshot of the affected entities is required to realign the target.
|
While the problem is unresolved, monitor the size of the |
Confirming the diagnosis
A useful discriminator: if the same PostgreSQL server is also used as a target by another pipeline, that pipeline keeps working with no errors, because writing to the target does not go through logical decoding. Network reachability, credentials and grants are ruled out by that alone.
-
Check the running version and date the restart that activated the restriction:
SELECT version(); SELECT pg_postmaster_start_time(); -
Inspect the parameter:
SELECT name, setting, boot_val, source, context, pending_restart FROM pg_settings WHERE name = 'output_plugin_libraries';if this query returns no rows, the server does not have the security update and the cause of the failure is something else. -
List the replication slots and check which ones are no longer advancing:
SELECT slot_name, plugin, active, wal_status, restart_lsn, confirmed_flush_lsn FROM pg_replication_slots; -
Reproduce the refusal directly, connected to the database used by the pipeline:
SELECT pg_create_logical_replication_slot('gs_test_wal2json', 'wal2json');The statement fails with the same message when the restriction is in place. If it succeeds, drop the slot immediately, because an unused slot retains WAL:
SELECT pg_drop_replication_slot('gs_test_wal2json');
Resolution
|
The list must be extended, not replaced. Other replication tools running against the same server may rely on their own output plugins, and overwriting the value would silently disable them. Include every plugin that must stay allowed as its own SQL string literal: any names from |
ALTER SYSTEM SET with a single SQL string of comma-separated names stores one list element, the whole quoted string. CREATE SLOT then still fails with library "wal2json" may not be used as an output plugin. The working form uses a separate SQL string literal for each plugin.
-
Read the live value and the plugins already in use:
SELECT name, setting, source, sourcefile FROM pg_settings WHERE name = 'output_plugin_libraries'; SELECT DISTINCT plugin FROM pg_replication_slots WHERE plugin IS NOT NULL; -
Reset any value previously written by
ALTER SYSTEM, then set the allowlist with separate string literals, reload, and confirm:ALTER SYSTEM RESET output_plugin_libraries; ALTER SYSTEM SET output_plugin_libraries = 'pgoutput', 'test_decoding', 'wal2json'; SELECT pg_reload_conf(); SELECT name, setting, source, sourcefile FROM pg_settings WHERE name = 'output_plugin_libraries'; -- expected setting: pgoutput, test_decoding, wal2json -- NO extra quotes around the whole list -- sourcefile: .../postgresql.auto.conf SELECT pg_create_logical_replication_slot('gs_test_wal2json', 'wal2json'); SELECT pg_drop_replication_slot('gs_test_wal2json');Add any other plugin from the slots query as a further SQL string literal in the same
SET. A reload is enough; a restart is not required. Do not drop existinggs_*slots.If
SHOW output_plugin_librariesorpg_settings.settingstill has quotes around the whole list (it looks like"pgoutput, test_decoding, wal2json"as one name), the value is poisoned: PostgreSQL stored one list element. That is the stuck state created by setting the GUC from a single quoted comma-separated string. RunRESETthenSETwith separate literals, as above.
ALTER SYSTEM writes postgresql.auto.conf in the data directory. That file wins over /etc/postgresql/…/postgresql.conf. A missing line in the /etc file does not mean the GUC is unset.
The same change can be applied in postgresql.conf instead. That syntax is different from ALTER SYSTEM SET, and it must be done after ALTER SYSTEM RESET output_plugin_libraries;, otherwise the poisoned postgresql.auto.conf value still wins:
output_plugin_libraries = 'pgoutput, test_decoding, wal2json'
Then run SELECT pg_reload_conf();. A reload is enough; a restart is not required.
Once the test CREATE SLOT succeeds, entities that were already in CDC resume from the checkpoint on their own at the next retry. No checkpoint reset and no pipeline reconfiguration are required. A snapshot is needed only for pipelines created after the upgrade, where the replication slot was never created.
if PostgreSQL is maintained with automatic updates, set output_plugin_libraries explicitly now, so that future upgrades cannot reintroduce the problem.
|