{"record":{"id":"754c5d68e0f38926","repo":"googleapis/mcp-toolbox","slug":"invalid-source-for-q-tool-source-q-is-not-a-com-754c5d","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/elasticsearch/elasticsearchesql/elasticsearchesql.go","lineNumber":102,"sourceCode":"\t\t\ttools.GetAnnotationsOrDefault(c.Annotations, tools.NewReadOnlyAnnotations),\n\t\t\ttools.Manifest{Description: c.Description, Parameters: c.Parameters.Manifest(), AuthRequired: c.AuthRequired},\n\t\t\tc.Parameters,\n\t\t),\n\t}, nil\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\tvar cancel context.CancelFunc\n\tif t.Cfg.Timeout > 0 {\n\t\tctx, cancel = context.WithTimeout(ctx, time.Duration(t.Cfg.Timeout)*time.Second)\n\t\tdefer cancel()\n\t} else {\n\t\tctx, cancel = context.WithTimeout(ctx, time.Minute)\n\t\tdefer cancel()\n\t}\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql.go#L84-L120","documentation":"Tool.ValidateSource in elasticsearchesql.go checks that the source attached to the tool implements the tool's private `compatibleSource` interface (i.e. it is an Elasticsearch source, not some other database source). If the Go type assertion `source.(compatibleSource)` fails, the toolbox cannot run ES|QL against that source and refuses to register/serve the tool. This is a configuration-time type mismatch between the tool and its bound source.","triggerScenarios":"Declaring a tool of kind `elasticsearch-esql` whose `source` field references a source defined with a different SourceConfigType (e.g. a Postgres, AlloyDB or CloudSQL source) so that ValidateSource receives a sources.Source that does not satisfy compatibleSource.","commonSituations":"Copy-pasting a tools.yaml between configs and pointing esql tools at a non-Elasticsearch source; renaming a source but leaving the tool's `source:` key bound to an old unrelated source; composing prebuilt configs where the source kind was changed to a different database.","solutions":["Point the tool's `source` field at a source of kind `elasticsearch` in tools.yaml","Check the source's `kind` value under `sources:` matches what this tool requires (elasticsearch)","If you meant a different database, use that engine's SQL tool type instead of elasticsearch-esql","Re-run toolbox and verify with `toolbox --tools-file` / the tools endpoint that the tool loads"],"exampleFix":"// before (tools.yaml)\ntools:\n  run-esql:\n    kind: elasticsearch-esql\n    source: my-postgres-source\n// after\ntools:\n  run-esql:\n    kind: elasticsearch-esql\n    source: my-elasticsearch-source","handlingStrategy":"validation","validationCode":"// Before serving/using the tool, verify the bound source kind in tools.yaml:\n// yamlPath: tools.<name>.source -> sources.<srcName>.kind == \"elasticsearch\"\nfunc sourceKindIs(cfg map[string]any, toolName, want string) bool {\n    tools := cfg[\"tools\"].(map[string]any)\n    t := tools[toolName].(map[string]any)\n    srcName := t[\"source\"].(string)\n    src := cfg[\"sources\"].(map[string]any)[srcName].(map[string]any)\n    return src[\"kind\"] == want\n}\n// sourceKindIs(cfg, \"run-esql\", \"elasticsearch\")","typeGuard":"// Mirrors the library check: assert the source implements the compatible interface.\nif esSrc, ok := src.(elasticsearchesql.CompatibleSource); ok {\n    _ = esSrc // safe to use with the esql tool\n} else {\n    return fmt.Errorf(\"source %T is not an Elasticsearch source\", src)\n}","tryCatchPattern":"if err := tool.ValidateSource(src); err != nil {\n    log.Fatalf(\"tool %s misconfigured: %v\", toolName, err)\n}","preventionTips":["Keep one source per engine with an unambiguous name (e.g. `elasticsearch-prod`)","After editing tools.yaml, run the toolbox once locally to catch validation errors before deploy","Lint tools.yaml in CI: assert each tool's source kind matches the tool family","Never reuse a source name across engines in multi-source configs"],"tags":["go","configuration","source-binding","type-mismatch"],"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"}