Hi! 👋 We are doing a big documentation refresh. Help us improve — what's missing or could be better? Let us know! Simply send an email or start a conversation in Google Groups!

Troubleshoot the DuckDB plugin

Plugin does not load

cannot open shared object file

Confirm the plugins entry uses the installed absolute path and that the ProxySQL service account can read the .so and traverse its parent directories. Check the loader error for any missing shared-library dependency too.

ABI or DEBUG mismatch

Install a core and plugin built together with the same tier and build mode. A DEBUG core requires a DEBUG plugin; release requires release. When rebuilding, clean stale objects after changing modes and use PROXYSQL40=1 on every build invocation. Follow the Installation guide.

DuckDB source archive fails verification during build

From the ProxySQL source root, run:

bash deps/duckdb/verify-source.bash

Inspect the checksum or corrupt-archive diagnostic. If the vendored archive is missing or damaged, restore it from the matching source checkout before rebuilding.

Engine fails to open

File or directory permission error

Check duckdb-database_path, parent-directory existence, ownership, service sandbox rules, and permissions for the ProxySQL operating-system account. Writable databases need write access to their containing directory as well as the database file. Use an absolute path to avoid opening a different file when the service’s working directory changes.

Read-only in-memory configuration

duckdb-read_only=true cannot use :memory: or an empty database path. Configure an existing file-backed database or disable read-only mode, save the corrected configuration, and restart ProxySQL.

Invalid memory limit or engine setting

Inspect the startup log for the setting named in a duckdb_set_config error or the database-open error. Correct the saved value before restarting again. For a running plugin, LOAD validates duckdb-memory_limit before applying live changes.

Listener does not start

Check whether the configured address exists locally and whether another process or ProxySQL listener is using the port. Use a dedicated port for each listener. Common defaults are:

  • 6031: DuckDB MySQL protocol
  • 6032: ProxySQL Admin
  • 6033: normal ProxySQL MySQL listener
  • 6034: DuckDB PostgreSQL protocol

An empty listener value disables that protocol. After changing duckdb-mysql_ifaces or duckdb-pgsql_ifaces, save to Disk and restart ProxySQL. LOAD does not rebind sockets.

Authentication fails

Use a frontend credential in the correct table:

  • MySQL endpoint: mysql_users
  • PostgreSQL endpoint: pgsql_users

Confirm the user is active, enabled for frontend use, and loaded to Runtime. Use LOAD MYSQL USERS TO RUNTIME or LOAD PGSQL USERS TO RUNTIME after editing the corresponding table, and save users to Disk if they must survive restart. A user needs a corresponding entry in each table to authenticate through both protocols. See the Quickstart for examples.

Connection resets immediately

Check duckdb-max_connections and application connection-pool sizes. At the cap, the plugin closes new sockets before protocol setup, so clients may show EOF or a reset instead of a descriptive error. Lowering the cap preserves existing connections.

If connections stall during authentication, check the ProxySQL log for a Closing not established DuckDB client connection warning and review mysql-connect_timeout_client or pgsql-connect_timeout_client for that endpoint. Also check for startup or shutdown activity.

Query syntax works in MySQL or PostgreSQL but fails here

The endpoint protocol does not select the SQL dialect. Write DuckDB SQL. Only a small set of discovery and session commands is handled for compatibility.

Start with:

SELECT 42;

Then reduce the failing statement to identify unsupported syntax, missing objects, permissions, or a driver protocol mode. See Protocol compatibility.

Prepared statement or parameterized query fails

The listeners do not support client-visible prepared statements. MySQL clients receive Command not supported (error 1045, SQLSTATE 28000) when preparing a statement, even after successful authentication. PostgreSQL extended-query requests return SQLSTATE 0A000.

Configure the driver for simple-query mode or use a non-prepared text-query API. Check that the driver’s parameter API can safely encode values in that mode; do not concatenate untrusted input into SQL. If the driver requires server-side prepared statements, choose another compatible client or access method.

Multiple SQL statements are rejected

Send one statement per request. For example, send SET NAMES utf8 and SELECT 1 separately; sending SET NAMES utf8; SELECT 1 as one request is rejected. Check driver connection initialization settings for batches of SQL statements.

Values arrive as strings

Both protocols advertise text columns. Parse results according to the expected query schema instead of relying on MySQL or PostgreSQL numeric or date type metadata. Set explicit result-conversion rules in your application where the driver permits them.

A special DuckDB value arrives as NULL

Some result types, such as UUIDs and nested values, need conversion to text. For ordinary queries the plugin normally performs this conversion. Certain statements, including DML with RETURNING, cannot use that conversion and may return NULL for an unsupported type even when the stored value is not NULL.

Cast the affected expression explicitly in the original statement. For example, if items.id is a UUID:

INSERT INTO items (id) VALUES (UUID()) RETURNING id::VARCHAR;

Configuration changed but behavior did not

Compare the editable and running values through ProxySQL Admin:

SELECT variable_name, variable_value FROM global_variables
WHERE variable_name LIKE 'duckdb-%' ORDER BY variable_name;

SELECT variable_name, variable_value FROM runtime_global_variables
WHERE variable_name LIKE 'duckdb-%' ORDER BY variable_name;

For a live change, run LOAD DUCKDB VARIABLES TO RUNTIME and inspect any error. An invalid value or pending restart change in Main causes the request to fail, including other valid live edits. Correct those values before retrying.

For listener addresses, database path, read-only mode, or enabling external access, save Main with SAVE DUCKDB VARIABLES TO DISK and restart ProxySQL. Runtime shows what is in effect until then. See the Admin reference.

Configuration disappears after restart

LOAD applies changes without saving them. After reviewing Main, persist it:

SAVE DUCKDB VARIABLES TO DISK;

Verify the saved duckdb-* rows in disk.global_variables. Saving Runtime to Memory first will replace Main and discard any pending edits, so use that command only if the running settings are the ones you intend to keep.

External file access is denied

External access is disabled by default. Review the Security guide before enabling it. To enable it deliberately, edit duckdb-enable_external_access in Main, save to Disk, and restart ProxySQL. LOAD cannot enable it while the database is open. Also verify the ProxySQL account’s filesystem permissions and any service sandbox restrictions.

A query consumes excessive resources

The plugin has no per-query execution timeout. Bound application concurrency, review duckdb-memory_limit, choose a conservative duckdb-threads value, and reduce duckdb-max_connections as needed; all three settings apply live. The memory limit is not a cap on total process memory, and reducing the connection limit does not stop existing sessions or queries.

If a running query must stop and the client cannot cancel it, a controlled ProxySQL restart may be necessary. Include normal ProxySQL traffic in that recovery plan. A restart loses in-memory DuckDB data and interrupts active work.