apache/shardingsphere · error · PipelineInternalException

Unsupported PostgreSQL version: %s

Error message

Unsupported PostgreSQL version: %s

What it means

The PostgreSQL incremental position manager needs the current WAL LSN to seed incremental ingestion. It picks a SQL function by server version: PG_CURRENT_XLOG_LOCATION for 9.6 and PG_CURRENT_WAL_LSN for 10+. Any older server (or a version metadata report it cannot classify) triggers a PipelineInternalException naming the exact product version string.

Source

Thrown at kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/ingest/incremental/wal/position/PostgreSQLIncrementalPositionManager.java:70

    }
    
    private WALPosition getWALPosition(final Connection connection, final String logSequenceNumberSQL) throws SQLException {
        try (
                PreparedStatement preparedStatement = connection.prepareStatement(logSequenceNumberSQL);
                ResultSet resultSet = preparedStatement.executeQuery()) {
            resultSet.next();
            return new WALPosition(new PostgreSQLLogSequenceNumber(LogSequenceNumber.valueOf(resultSet.getString(1))));
        }
    }
    
    private String getLogSequenceNumberSQL(final DatabaseMetaData metaData) throws SQLException {
        if (9 == metaData.getDatabaseMajorVersion() && 6 <= metaData.getDatabaseMinorVersion()) {
            return "SELECT PG_CURRENT_XLOG_LOCATION()";
        }
        if (10 <= metaData.getDatabaseMajorVersion()) {
            return "SELECT PG_CURRENT_WAL_LSN()";
        }
        throw new PipelineInternalException("Unsupported PostgreSQL version: " + metaData.getDatabaseProductVersion());
    }
    
    @Override
    public void destroy(final DataSource dataSource, final String slotNameSuffix) throws SQLException {
        try (Connection connection = dataSource.getConnection()) {
            slotManager.dropIfExisted(connection, slotNameSuffix);
        }
    }
    
    @Override
    public String getDatabaseType() {
        return "PostgreSQL";
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Use PostgreSQL 9.6+ (ideally 10+) as the pipeline source; upgrade the source server.
  2. Verify the actual server behind the JDBC URL with SELECT version(); a proxy or pgbouncer routing may point at an older instance than intended.
  3. If stuck on an old version in a fork, extend getLogSequenceNumberSQL to handle its version and LSN function, but this requires a code change and is unsupported upstream.
Defensive patterns

Strategy: validation

Validate before calling

try (Connection conn = dataSource.getConnection()) {
    DatabaseMetaData md = conn.getMetaData();
    int major = md.getDatabaseMajorVersion(), minor = md.getDatabaseMinorVersion();
    if (major < 9 || (9 == major && minor < 6)) {
        throw new IllegalStateException("PostgreSQL 9.6+ required, got " + md.getDatabaseProductVersion());
    }
}

Try / catch

try {
    position = positionManager.getPosition(dataSource);
} catch (final PipelineInternalException ex) {
    // surface version string and abort job setup before slot creation
    throw ex;
}

Prevention

When it happens

Trigger: Calling getPosition(...) on a PostgreSQL connection whose DatabaseMetaData reports major version < 9, or 9 with minor < 6. Typically happens at migration/CDC job start when the position manager opens a connection and queries metadata before choosing the LSN function.

Common situations: Pointing a migration or CDC source at PostgreSQL 9.5 or older (or a very old Greenplum/compatible fork reporting old version numbers); misrouted connection that lands on an unexpected database; product version strings from proxies that confuse metadata.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/1af227f4a6339edd. Report an issue: GitHub.