{"record":{"id":"66ebee6afd797fc7","repo":"googleapis/mcp-toolbox","slug":"invalid-source-for-q-tool-source-q-is-not-a-com-66ebee","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":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/looker/lookerlistagents/lookerlistagents.go","lineNumber":111,"sourceCode":"// validate interface\nvar _ tools.Tool = Tool{}\n\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\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\tlogger, err := util.LoggerFromContext(ctx)\n\tif err != nil {\n\t\treturn nil, util.NewClientServerError(\"unable to get logger from ctx\", http.StatusInternalServerError, err)\n\t}\n\n\tsdk, err := source.GetLookerSDK(ctx, string(accessToken))\n\tif err != nil {\n\t\treturn nil, util.NewClientServerError(fmt.Sprintf(\"error getting sdk: %v\", err), http.StatusInternalServerError, err)\n\t}","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/looker/lookerlistagents/lookerlistagents.go#L93-L129","documentation":"Tool.ValidateSource checks that the configured source implements the lookerlistagents compatibleSource interface before the tool runs. If the sources.Source value passed in does not satisfy the interface (it is not the looker source), validation fails with this error and the tool refuses to execute. It is an upfront guard so Invoke never operates on an incompatible backend.","triggerScenarios":"The server validates the tool's source binding at startup or per-request and finds a concrete source type that is not *sources/looker.Source — e.g. tools.yaml binds looker-list-agents to a postgres/http source, or a custom source lacks the compatibleSource methods.","commonSituations":"Wrong source name in tools.yaml after refactoring; multiple environments (dev/prod) with different source sets; registering a custom source that implements sources.Source but not UseClientAuthorization/GetAuthTokenHeaderName.","solutions":["Bind the tool to a source whose kind is 'looker' in the YAML config.","Check startup logs that the named source initialized as a looker source.","For custom sources, implement the compatibleSource methods.","Compare the source name in the tool config against the sources section for typos."],"exampleFix":"// before (tools.yaml)\nsources:\n  pg: { kind: postgres, ... }\ntools:\n  list-agents: { kind: looker-list-agents, source: pg }\n\n// after\nsources:\n  looker-prod: { kind: looker, baseUrl: https://looker.example.com, ... }\ntools:\n  list-agents: { kind: looker-list-agents, source: looker-prod }","handlingStrategy":"type-guard","validationCode":"if err := tool.ValidateSource(src); err != nil {\n    return fmt.Errorf(\"startup validation failed: %w\", err)\n}","typeGuard":"func validateLookerSource(s sources.Source) error {\n    if _, ok := s.(*lookersrc.Source); !ok {\n        return fmt.Errorf(\"expected looker source, got %T\", s)\n    }\n    return nil\n}","tryCatchPattern":"if err := tool.ValidateSource(src); err != nil {\n    log.Fatalf(\"looker-list-agents bound to incompatible source: %v\", err)\n}","preventionTips":["Call ValidateSource for every tool/source pair at server startup.","Name sources by kind (e.g. looker-prod) to make mismatches obvious.","Add CI checks that parse tools.yaml and assert tool kinds match source kinds.","Verify environment-specific configs still reference looker sources after refactors."],"tags":["looker","mcp","configuration","type-assertion"],"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"}