feat(alloydb): provide actionable error when read-only mode is used on pre-PG17 - #3902
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds error handling to the AlloyDB source initialization to provide a clearer error message when read-only mode is requested on unsupported PostgreSQL versions (pre-PG17). The reviewer noted that the error check added immediately after initAlloyDBPgConnectionPool is unreachable because that function only initializes the pool structure without establishing a network connection, and recommended removing this redundant check while keeping the one after pool.Ping.
58d60a7 to
3c3395a
Compare
3c3395a to
c0ea3ec
Compare
8a7c65d to
9a65616
Compare
Thanks for the suggestion! I had originally thought not to put the exact version number in the error message because it won't be the same (new versions being supported soon). Although I think it's ok if we put it because it might not show up for the most part anyway :) |
9a65616 to
fe1258f
Compare
|
@anubhav756 with the |
fe1258f to
8a1c28c
Compare
8a1c28c to
d769884
Compare
d769884 to
3031b46
Compare
3031b46 to
b900fa7
Compare
b900fa7 to
5402b75
Compare
5402b75 to
246d76d
Compare
|
🧨 Preview deployments removed. Cloudflare Pages environments for |
…ly mode is used on pre-PG17 (#3902) ## Overview Shows a clear, helpful error message if someone turns on `readOnly: true` on an older AlloyDB database that doesn't support read-only mode yet. ## Context * AlloyDB locks connections into read-only mode using a special setting (`alloydb_session_read_only`). * This setting works out of the box on newer Postgres versions (17+), but older versions that haven't received recent updates don't recognize it and fail with a cryptic database error (`unrecognized configuration parameter`). * Previously, Toolbox just showed a generic `"unable to connect"` error, giving users no clue what went wrong. ## Changes 1. If an instance rejects the read-only setting, Toolbox now explains that the database version doesn't support it, tells the user to make sure their instance has the latest Postgres version, and links directly to our [AlloyDB documentation](https://mcp-toolbox.dev/integrations/alloydb/source/#reference). 2. Added a note to the documentation clarifying that if users run into this error, they should make sure their database has the latest Postgres updates.
…ly mode is used on pre-PG17 (googleapis#3902) ## Overview Shows a clear, helpful error message if someone turns on `readOnly: true` on an older AlloyDB database that doesn't support read-only mode yet. ## Context * AlloyDB locks connections into read-only mode using a special setting (`alloydb_session_read_only`). * This setting works out of the box on newer Postgres versions (17+), but older versions that haven't received recent updates don't recognize it and fail with a cryptic database error (`unrecognized configuration parameter`). * Previously, Toolbox just showed a generic `"unable to connect"` error, giving users no clue what went wrong. ## Changes 1. If an instance rejects the read-only setting, Toolbox now explains that the database version doesn't support it, tells the user to make sure their instance has the latest Postgres version, and links directly to our [AlloyDB documentation](https://mcp-toolbox.dev/integrations/alloydb/source/#reference). 2. Added a note to the documentation clarifying that if users run into this error, they should make sure their database has the latest Postgres updates.
…ly mode is used on pre-PG17 (googleapis#3902) ## Overview Shows a clear, helpful error message if someone turns on `readOnly: true` on an older AlloyDB database that doesn't support read-only mode yet. ## Context * AlloyDB locks connections into read-only mode using a special setting (`alloydb_session_read_only`). * This setting works out of the box on newer Postgres versions (17+), but older versions that haven't received recent updates don't recognize it and fail with a cryptic database error (`unrecognized configuration parameter`). * Previously, Toolbox just showed a generic `"unable to connect"` error, giving users no clue what went wrong. ## Changes 1. If an instance rejects the read-only setting, Toolbox now explains that the database version doesn't support it, tells the user to make sure their instance has the latest Postgres version, and links directly to our [AlloyDB documentation](https://mcp-toolbox.dev/integrations/alloydb/source/#reference). 2. Added a note to the documentation clarifying that if users run into this error, they should make sure their database has the latest Postgres updates.
…ly mode is used on pre-PG17 (googleapis#3902) ## Overview Shows a clear, helpful error message if someone turns on `readOnly: true` on an older AlloyDB database that doesn't support read-only mode yet. ## Context * AlloyDB locks connections into read-only mode using a special setting (`alloydb_session_read_only`). * This setting works out of the box on newer Postgres versions (17+), but older versions that haven't received recent updates don't recognize it and fail with a cryptic database error (`unrecognized configuration parameter`). * Previously, Toolbox just showed a generic `"unable to connect"` error, giving users no clue what went wrong. ## Changes 1. If an instance rejects the read-only setting, Toolbox now explains that the database version doesn't support it, tells the user to make sure their instance has the latest Postgres version, and links directly to our [AlloyDB documentation](https://mcp-toolbox.dev/integrations/alloydb/source/#reference). 2. Added a note to the documentation clarifying that if users run into this error, they should make sure their database has the latest Postgres updates.
The branch was cut before #3902, #3905 and #3921 landed, and rebasing it took its own side of four files that main had since moved on. - alloydbpg: #3902's read-only diagnostic was dropped, so a pre-PG17 instance with readOnly set failed with a bare "unrecognized configuration parameter" instead of the message the docs tell users to expect. Restored inside the connect closure, where the ping now lives. - tests/tool.go: list_active_queries went back to a version that does not scope its rows by application_name, which is the flake main had already fixed. - tests/alloydbainl: the question asked of the NL model was weakened while the assertion still expected the aliased column, so the test failed on a correct answer. - tests/dataplex: cleanup threshold went back to an inline literal. #3921's close-on-failure survives everywhere: it moved into the connect closure along with the ping it guards.
Every source builds its handle through sources.ConnectOnce and reaches it through an accessor, instead of connecting inline in Initialize and storing the result on an exported field. Initialize takes a deferConnect parameter, but the only caller passes false, so each source still connects during startup and still reports a connect failure there. The flag that sets it lands separately. Config that needs no network is resolved in newSource, which runs whether or not the connect is deferred: a malformed queryTimeout, baseUrl or writeMode is a configuration error and must fail at startup rather than on the first tool call. Sources keep their context-free accessors, which report the handle only once connected. They exist so tools can express a capability as an interface and type-assert on it; none of them is invoked. The exception is Looker, where LookerApiSettings is read after GetLookerSDK has connected. The branch was cut before #3902, #3905 and #3921 landed, so it also restores alloydbpg's pre-PG17 read-only diagnostic and three test files it would otherwise have reverted, and detaches the bigquery client creator from the connect's context, which is cancelled as soon as the connect returns.
Every source builds its handle through sources.ConnectOnce and reaches it through an accessor, instead of connecting inline in Initialize and storing the result on an exported field. Initialize takes a deferConnect parameter, but the only caller passes false, so each source still connects during startup and still reports a connect failure there. The flag that sets it lands separately. Config that needs no network is resolved in newSource, which runs whether or not the connect is deferred: a malformed queryTimeout, baseUrl or writeMode is a configuration error and must fail at startup rather than on the first tool call. Sources keep their context-free accessors, which report the handle only once connected. They exist so tools can express a capability as an interface and type-assert on it; none of them is invoked. The exception is Looker, where LookerApiSettings is read after GetLookerSDK has connected. ConnectOnce bounds the attempt at ConnectTimeout, which the startup connect did not have before. Sources whose own config permits a longer connect raise the ceiling to match, as postgres and looker already did: mysql, oceanbase, singlestore and mindsdb through the driver read timeout the ping honours, trino through the timeout it sends with that query, and cockroachdb through the backoff its retry loop sleeps. The branch was cut before #3902, #3905 and #3921 landed, so it also restores alloydbpg's pre-PG17 read-only diagnostic and three test files it would otherwise have reverted, detaches the bigquery client creator from the connect's context, and stops InitConnectionSpan panicking on the nil tracer that some source tests still pass.
Every source builds its handle through sources.ConnectOnce and reaches it through an accessor, instead of connecting inline in Initialize and storing the result on an exported field. Initialize takes a deferConnect parameter, but the only caller passes false, so each source still connects during startup and still reports a connect failure there. The flag that sets it lands separately. Config that needs no network is resolved in newSource, which runs whether or not the connect is deferred: a malformed queryTimeout, baseUrl or writeMode is a configuration error and must fail at startup rather than on the first tool call. Sources keep their context-free accessors, which report the handle only once connected. They exist so tools can express a capability as an interface and type-assert on it; none of them is invoked. The exception is Looker, where LookerApiSettings is read after GetLookerSDK has connected. ConnectOnce bounds the attempt at ConnectTimeout, which the startup connect did not have before. Sources whose own config permits a longer connect raise the ceiling to match, as postgres and looker already did: mysql, oceanbase, singlestore and mindsdb through the driver read timeout the ping honours, trino through the timeout it sends with that query, and cockroachdb through the backoff its retry loop sleeps. The branch was cut before #3902, #3905 and #3921 landed, so it also restores alloydbpg's pre-PG17 read-only diagnostic and three test files it would otherwise have reverted, detaches the bigquery client creator from the connect's context, and stops InitConnectionSpan panicking on the nil tracer that some source tests still pass.
🤖 I have created a release *beep* *boop* --- ## [1.11.0](v1.10.0...v1.11.0) (2026-09-10) ### Features * Add Toolbox version check on startup ([#3837](#3837)) ([7d36de3](7d36de3)) * **alloydb:** Provide actionable error when read-only mode is used on pre-PG17 ([#3902](#3902)) ([28ace11](28ace11)) * **MCP Apps:** Add support for MCP Apps ([#4008](#4008)) ([9cf3e95](9cf3e95)) * **MCPResources:** Add support for MCP Resources ([#3968](#3968)) ([fb227b0](fb227b0)) * **mcp:** Serve groups/list and groups/get as a Toolbox extension ([#3914](#3914)) ([eaf2a9c](eaf2a9c)) * **source/bigquery:** Attach SQLCommenter attributes as BigQuery job labels ([#3843](#3843)) ([bf0f1a5](bf0f1a5)) * **sources:** Add ConnectOnce, a helper for connecting on first use ([#3905](#3905)) ([16c31fa](16c31fa)) ### Bug Fixes * **docs/cloudgda:** Document context fields, fix PSV example and links ([#3919](#3919)) ([ae47535](ae47535)) * **looker:** Update want clause ([#3962](#3962)) ([9593321](9593321)) * **source/http:** Block IETF protocol assignments range in default SSRF guard ([#3909](#3909)) ([4302e86](4302e86)) * **sources:** Release the handle when a source fails to connect ([#3921](#3921)) ([0001190](0001190)) * **test/alloydbainl:** Use explicit SQL alias prompt in integration test ([#3916](#3916)) ([596eaf9](596eaf9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
mcp-toolbox 1.11.0 Created-by: HarmonybrewBot Commit-by: HarmonybrewBot Merged-by: HarmonybrewBot Description: Created by `brew bump` --- Created with `brew bump-formula-pr`.<details> <summary>release notes</summary> <pre>## [1.11.0](googleapis/mcp-toolbox@v1.10.0...v1.11.0) (2026-09-10) ### Features * Add Toolbox version check on startup ([#3837](googleapis/mcp-toolbox#3837)) ([7d36de3](googleapis/mcp-toolbox@7d36de3)) * **alloydb:** Provide actionable error when read-only mode is used on pre-PG17 ([#3902](googleapis/mcp-toolbox#3902)) ([28ace11](googleapis/mcp-toolbox@28ace11)) * **MCP Apps:** Add support for MCP Apps ([#4008](googleapis/mcp-toolbox#4008)) ([9cf3e95](googleapis/mcp-toolbox@9cf3e95)) * **MCPResources:** Add support for MCP Resources ([#3968](googleapis/mcp-toolbox#3968)) ([fb227b0](googleapis/mcp-toolbox@fb227b0)) * **mcp:** Serve groups/list and groups/get as a Toolbox extension ([#3914](googleapis/mcp-toolbox#3914)) ([eaf2a9c](googleapis/mcp-toolbox@eaf2a9c)) * **source/bigquery:** Attach SQLCommenter attributes as BigQuery job labels ([#3843](googleapis/mcp-toolbox#3843)) ([bf0f1a5](googleapis/mcp-toolbox@bf0f1a5)) * **sources:** Add ConnectOnce, a helper for connecting on first use ([#3905](googleapis/mcp-toolbox#3905)) ([16c31fa](googleapis/mcp-toolbox@16c31fa)) ### Bug Fixes * **docs/cloudgda:** Document context fields, fix PSV example and links ([#3919](googleapis/mcp-toolbox#3919)) ([ae47535](googleapis/mcp-toolbox@ae47535)) * **looker:** Update want clause ([#3962](googleapis/mcp-toolbox#3962)) ([9593321](googleapis/mcp-toolbox@9593321)) * **source/http:** Block IETF protocol assignments range in default SSRF guard ([#3909](googleapis/mcp-toolbox#3909)) ([4302e86](googleapis/mcp-toolbox@4302e86)) * **sources:** Release the handle when a source fails to connect ([#3921](googleapis/mcp-toolbox#3921)) ([0001190](googleapis/mcp-toolbox@0001190)) * **test/alloydbainl:** Use explicit SQL alias prompt in integration test ([#3916](googleapis/mcp-toolbox#3916)) ([596eaf9](googleapis/mcp-toolbox@596eaf9)) | **OS/Architecture** | **Description** | **SHA256 Hash** | | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | | [linux/amd64](https://storage.googleapis.com/mcp-toolbox-for-databases/v1.11.0/linux/amd64/toolbox) ([Signature](https://storage.googleapis.com/mcp-toolbox-for-databases/v1.11.0/linux/amd64/toolbox.asc)) | For **Linux** systems running on **Intel/AMD 64-bit processors**. | 4d86b7c75916e2de721b9dc9dfb681f9a29fe4a8a01779007b2f6b1f5819296c | | [darwin/arm64](https://storage.googleapis.com/mcp-toolbox-for-databases/v1.11.0/darwin/arm64/toolbox) | For **macOS** systems running on **Apple Silicon** (M1, M2, M3, etc.) processors. | 5e94db330b5ec77a916c4670ec1337d97abbb9865b13a705f81f87ca14592307 | | [darwin/amd64](https://storage.googleapis.com/mcp-toolbox-for-databases/v1.11.0/darwin/amd64/toolbox) | For **macOS** systems running on **Intel processors**. | 4a05bc786302571823f8c10b0ed2ce4f219c4a05c9899e91a9743ca8ec932743 | | [windows/amd64](https://storage.googleapis.com/mcp-toolbox-for-databases/v1.11.0/windows/amd64/toolbox.exe) | For **Windows** systems running on **Intel/AMD 64-bit processors**. | 3c8c46d8efad225636e341fcdb137557779ee1c1b0c362d1b4870901c2668ccf | | [windows/arm64](https://storage.googleapis.com/mcp-toolbox-for-databases/v1.11.0/windows/arm64/toolbox.exe) | For **Windows** systems running on **ARM 64-bit processors**. | feb2d0d55c003b30af7a9afa22f11721239c70cc21812a2de66c425de76a2153 |</pre> <p>View the full release notes at <a href="https://github.com/googleapis/mcp-toolbox/releases/tag/v1.11.0">https://github.com/googleapis/mcp-toolbox/releases/tag/v1.11.0</a>.</p> </details> <hr> See merge request: Harmonybrew/homebrew-core!19994
Overview
Shows a clear, helpful error message if someone turns on
readOnly: trueon an older AlloyDB database that doesn't support read-only mode yet.Context
alloydb_session_read_only).unrecognized configuration parameter)."unable to connect"error, giving users no clue what went wrong.Changes