{"record":{"id":"513819c191001d2d","repo":"googleapis/mcp-toolbox","slug":"tool-type-q-already-registered-513819","errorCode":null,"errorMessage":"tool type %q already registered","messagePattern":"tool type %q already registered","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/tools/datalineage/datalineagesearchlineage/datalineagesearchlineage.go","lineNumber":35,"sourceCode":"import (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\tlineagepb \"cloud.google.com/go/datacatalog/lineage/apiv1/lineagepb\"\n\t\"github.com/goccy/go-yaml\"\n\t\"github.com/googleapis/mcp-toolbox/internal/sources\"\n\t\"github.com/googleapis/mcp-toolbox/internal/tools\"\n\t\"github.com/googleapis/mcp-toolbox/internal/util\"\n\t\"github.com/googleapis/mcp-toolbox/internal/util/parameters\"\n)\n\nconst resourceType string = \"datalineage-search-lineage\"\n\nfunc init() {\n\tif !tools.Register(resourceType, newConfig) {\n\t\tpanic(fmt.Sprintf(\"tool type %q already registered\", resourceType))\n\t}\n}\n\nfunc newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) {\n\tactual := Config{ConfigBase: tools.ConfigBase{Name: name}}\n\tif err := decoder.DecodeContext(ctx, &actual); err != nil {\n\t\treturn nil, err\n\t}\n\treturn actual, nil\n}\n\ntype compatibleSource interface {\n\tSearchLineageStreaming(\n\t\tctx context.Context,\n\t\tparentLocation string,\n\t\tlocations []string,\n\t\trootEntities []*lineagepb.EntityReference,\n\t\tdirection lineagepb.SearchLineageStreamingRequest_SearchDirection,","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/datalineage/datalineagesearchlineage/datalineagesearchlineage.go#L17-L53","documentation":"This panic comes from init() in internal/tools/datalineage/datalineagesearchlineage: tools.Register(\"datalineage-search-lineage\", newConfig) returned false because the key already exists in the registry. The registry treats duplicate tool types as a programming error and the package panics immediately at startup. Each tool type key must be unique across the whole binary.","triggerScenarios":"A second declaration of the const \"datalineage-search-lineage\" elsewhere in the build registers the same key; or registration code is invoked a second time (tests, custom bootstrap) after package init.","commonSituations":"Copy-paste of the datalineage tool package without changing the const; merge conflicts reintroducing a duplicate; vendor/module duplication causing double init; test helpers re-running registration.","solutions":["Search the codebase for \"datalineage-search-lineage\" and delete or rename the duplicate const.","Ensure a single unique resourceType per tool package.","Deduplicate go.mod/vendor entries that could link the package twice.","Do not manually re-register init-registered tools in tests."],"exampleFix":"// before\nconst resourceType string = \"datalineage-search-lineage\" // also declared in another package\n// after\nconst resourceType string = \"datalineage-search-lineage\" // single declaration; duplicate removed","handlingStrategy":"validation","validationCode":"const want = \"datalineage-search-lineage\"\n// pre-change validation:\n//   git grep -n 'datalineage-search-lineage' -- '*.go'\n// one const declaration + one init() use = safe; anything more panics.","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"datalineage registration conflict: %v\", r)\n    }\n}()","preventionTips":["Assign a fresh, unique resourceType to every new tool package.","Detect duplicates in CI with a registry-key uniqueness test.","Confine registration to init(); skip manual re-registration in test scaffolding.","Avoid multiple module copies that would double-run init().","Review merge results for accidental duplicate tool definitions."],"tags":["go","panic","init","tool-registry","duplicate-registration"],"backgroundTag":"duplicate-tool-type-registration","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"}