googleapis/mcp-toolbox · error
invalid source for %q tool: source %q is not a compatible ty
Error message
invalid source for %q tool: source %q is not a compatible type
What it means
The Spanner execute-sql tool's ValidateSource checks that the resolved source implements the compatibleSource interface (a Spanner source exposing a *spanner.Client). If the source bound to this tool is a different kind of source (e.g. Postgres, SQLite), the type assertion fails and this error is returned. Tools may only run against sources of the matching engine type.
Source
Thrown at internal/tools/spanner/spannersql/spannersql.go:176
resp, err := source.RunSQL(ctx, t.Cfg.ReadOnly, newStatement, mapParams)
if err != nil {
return nil, util.ProcessGcpError(err)
}
return resp, nil
}
func (t Tool) GetSourceName() string {
return t.Cfg.Source
}
func (t Tool) ToConfig() tools.ToolConfig {
return t.Cfg
}
func (t Tool) ValidateSource(source sources.Source) error {
_, ok := source.(compatibleSource)
if !ok {
return fmt.Errorf("invalid source for %q tool: source %q is not a compatible type", t.Cfg.Type, t.Cfg.Source)
}
return nil
}
View on GitHub (pinned to 8cc6e09de2)
Solutions
- Change the tool's `source:` field in the YAML to the name of a source whose `kind` is `spanner`.
- Declare a `sources:` entry of kind `spanner` if none exists, then point the tool at it.
- If using multiple sources, verify each tool references the source matching its engine type.
- Add a startup config check so source/tool compatibility is validated before serving.
Example fix
# before
sources:
my-pg:
kind: postgres
uri: ...
tools:
run-query:
kind: spanner-execute-sql
source: my-pg
# after
sources:
my-spanner:
kind: spanner
project: my-project
instance: my-instance
database: my-db
tools:
run-query:
kind: spanner-execute-sql
source: my-spanner Defensive patterns
Strategy: type-guard
Validate before calling
# Validate before running: grep -A2 'kind: spanner' tools.yaml # confirm a spanner source exists # and that the tool's source: field references it yq '.tools[] | select(.kind == "spanner-execute-sql") | .source' tools.yaml
Type guard
func isSpannerSource(s sources.Source) bool {
_, ok := s.(spannersql.CompatibleSource)
return ok
} Try / catch
tool, err := myTool.ValidateSource(src)
if err != nil {
log.Fatalf("source binding mismatch: %v (check tools.yaml source: field)", err)
} Prevention
- Keep one source per engine and name tools after their source.
- Validate the full tools.yaml at startup before serving.
- Never share a single tool definition across different engine sources.
- Use schema/IDE validation for tools.yaml kinds and source refs.
When it happens
Trigger: Invoking or validating a spanner tool whose YAML config points `source` at a source declared with a kind other than `spanner`; programmatically passing a non-Spanner sources.Source to Tool.Invoke or ValidateSource.
Common situations: Copy-pasting a tools.yaml and forgetting to update the `source:` field; renaming sources so the tool binds to the wrong source; dynamically assembling configs where a generic SQL tool is attached to every source regardless of engine.
Related errors
- invalid source for %q tool: source %q is not a compatible ty
- invalid source for %q tool: source %q is not a compatible ty
- invalid source for %q tool: source %q is not a compatible ty
- description is required for tool %q
- invalid source for %q tool: source %q is not a compatible ty
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/eeadbb3e4a7a61cd.
Report an issue: GitHub.