{"record":{"id":"c9f6400cea2b5d97","repo":"googleapis/mcp-toolbox","slug":"invalid-source-for-q-tool-source-q-is-not-a-com-c9f640","errorCode":null,"errorMessage":"invalid source for %q tool: source %q is not a compatible type","messagePattern":"invalid source for %q tool: source %q is not a compatible type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go","lineNumber":100,"sourceCode":"}\n\n// Tool represents the list-clusters tool.\ntype Tool struct {\n\ttools.BaseTool[Config]\n}\n\nfunc (t Tool) GetSourceName() string {\n\treturn t.Cfg.Source\n}\n\nfunc (t Tool) ToConfig() tools.ToolConfig {\n\treturn t.Cfg\n}\n\nfunc (t Tool) ValidateSource(source sources.Source) error {\n\t_, ok := source.(compatibleSource)\n\tif !ok {\n\t\treturn fmt.Errorf(\"invalid source for %q tool: source %q is not a compatible type\", t.Cfg.Type, t.Cfg.Source)\n\t}\n\treturn nil\n}\n\n// buildParams builds the tool's parameters. A non-empty project means the source has a\n// configured default project, which is baked into the project param; otherwise the plain form is used.\nfunc buildParams(project string) parameters.Parameters {\n\tprojectParam := parameters.NewStringParameter(\"project\", \"The GCP project ID to list clusters for.\")\n\tif project != \"\" {\n\t\tprojectParam = parameters.NewStringParameter(\"project\", \"The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.\", parameters.WithStringDefault(project))\n\t}\n\treturn parameters.Parameters{\n\t\tprojectParam,\n\t\tparameters.NewStringParameter(\"location\", \"Optional: The location to list clusters in (e.g., 'us-central1'). Use '-' to list clusters across all locations.(Default: '-')\", parameters.WithStringDefault(\"-\")),\n\t}\n}\n\n// resolveParams builds the tool's parameters using the source's configured","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go#L82-L118","documentation":"ValidateSource checks that the source wired to this alloydb-list-clusters tool satisfies the compatibleSource interface (GetDefaultProject, UseClientAuthorization, ListCluster). If the configured source does not implement that interface, the tool cannot talk to the AlloyDB Admin API and this error is returned at config-validation time. It is a wiring/compatibility guard, not a runtime failure.","triggerScenarios":"Calling ValidateSource (directly or via server startup validation) with a sources.Source that is not the alloydb source (or another type implementing compatibleSource), e.g. a postgres or http source attached to this tool in tools.yaml.","commonSituations":"Misconfigured tools.yaml binding the tool to the wrong source name; copy-pasting a tool block across source kinds; renaming a source so the tool falls back to an unintended one; using a source that lacks a GCP project default.","solutions":["Check the tool's 'source' field in tools.yaml and point it at an alloydb source","Verify the referenced source's kind is alloydb (implements GetDefaultProject/UseClientAuthorization/ListCluster)","Run the toolbox config validation at startup and fix the reported tool-source pairing before deploying"],"exampleFix":"// before (tools.yaml)\ntools:\n  list-clusters:\n    kind: alloydb-list-clusters\n    source: my-postgres\n// after\ntools:\n  list-clusters:\n    kind: alloydb-list-clusters\n    source: my-alloydb","handlingStrategy":"validation","validationCode":"if _, ok := source.(alloydblistclusterscompatibleSource); !ok {\n    return fmt.Errorf(\"tool %s requires an alloydb-compatible source; got %T\", toolName, source)\n}","typeGuard":"func isAlloyDBSource(s sources.Source) bool {\n    _, ok := s.(interface {\n        GetDefaultProject() string\n        UseClientAuthorization() bool\n        ListCluster(context.Context, string, string, string) (any, error)\n    })\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Keep the tool's source field pointed at an alloydb source in tools.yaml","Run the toolbox config validation before deploying","Name sources with their kind suffix (e.g. my-alloydb) to avoid misbinding","Review tool-source pairings after any source rename"],"tags":["alloydb","configuration","type-mismatch","gcp"],"backgroundTag":"incompatible-source-type","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}