{"record":{"id":"294855c36a7245c0","repo":"googleapis/mcp-toolbox","slug":"invalid-source-for-q-tool-source-q-is-not-a-com-294855","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/alloydblistusers/alloydblistusers.go","lineNumber":101,"sourceCode":"}\n\n// Tool represents the list-users 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// Invoke executes the tool's logic.\nfunc (t Tool) Invoke(ctx context.Context, s sources.Source, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {\n\tsource, ok := s.(compatibleSource)\n\tif !ok {\n\t\treturn nil, util.NewClientServerError(\"source used is not compatible with the tool\", http.StatusInternalServerError, nil)\n\t}\n\tparamsMap := params.AsMap()\n\n\tproject, ok := paramsMap[\"project\"].(string)\n\tif !ok || project == \"\" {\n\t\treturn nil, util.NewAgentError(\"invalid or missing 'project' parameter; expected a string\", nil)\n\t}\n\tlocation, ok := paramsMap[\"location\"].(string)\n\tif !ok || location == \"\" {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/alloydb/alloydblistusers/alloydblistusers.go#L83-L119","documentation":"ValidateSource for alloydb-list-users checks that the attached source implements compatibleSource (GetDefaultProject, UseClientAuthorization, ListUser). Any other source type is rejected with this error because the tool can only invoke the AlloyDB Admin API through that interface. This is a startup-time wiring guard.","triggerScenarios":"ValidateSource called with a non-alloydb source — e.g. tools.yaml binds this tool to a firestore or spanner source.","commonSituations":"Mistyped source name resolving to the wrong source; template configs for other databases reused for AlloyDB; deleting/renaming the alloydb source but leaving the tool entry.","solutions":["Point the tool's source field at an alloydb source","Verify the source kind is alloydb in tools.yaml","Run config validation locally before deployment"],"exampleFix":"// before\nsource: my-spanner\n// after\nsource: my-alloydb","handlingStrategy":"validation","validationCode":"if !strings.HasPrefix(cfg.Source, \"alloydb\") {\n    return fmt.Errorf(\"tool %s expects an alloydb source, got %q\", cfg.Name, cfg.Source)\n}","typeGuard":"func isAlloyDBUserSource(s sources.Source) bool {\n    _, ok := s.(interface {\n        GetDefaultProject() string\n        UseClientAuthorization() bool\n        ListUser(context.Context, string, string, string) (any, error)\n    })\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Point list-users at an alloydb source only","Run the startup config validation","Use naming conventions to make source kinds obvious"],"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"}