{"record":{"id":"af08cbe96704d348","repo":"googleapis/mcp-toolbox","slug":"tool-type-q-already-registered-af08cb","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/dataplex/dataplexdiscovermetadata/dataplexdiscovermetadata.go","lineNumber":34,"sourceCode":"\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\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/tools/dataplex/dataplexcommon\"\n\t\"github.com/googleapis/mcp-toolbox/internal/util\"\n\t\"github.com/googleapis/mcp-toolbox/internal/util/parameters\"\n)\n\nconst resourceType string = \"dataplex-discover-metadata\"\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\tProjectID() string\n\tGenerateDataDiscovery(ctx context.Context, location, resourcePath string) (string, error)\n}\n\ntype Config struct {\n\ttools.ConfigBase `yaml:\",inline\"`","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/dataplex/dataplexdiscovermetadata/dataplexdiscovermetadata.go#L16-L52","documentation":"This panic comes from init() in internal/tools/dataplex/dataplexdiscovermetadata because tools.Register(\"dataplex-discover-metadata\", newConfig) returned false: the tool registry already contains that key. The library panics during startup so duplicate tool definitions can never silently replace one another. The fix is to ensure the resourceType is declared and registered exactly once.","triggerScenarios":"Duplicate const \"dataplex-discover-metadata\" elsewhere in the build whose init() also registers it; or an explicit second tools.Register call from test/bootstrap code after package init.","commonSituations":"Copy-pasted dataplex tool package with unchanged const; merges reintroducing duplicates; duplicate module copies under different import paths; tests exercising registration manually.","solutions":["Search the repository for \"dataplex-discover-metadata\" and delete or rename the duplicate declaration.","Ensure every tool package has a unique kebab-case resourceType.","Remove duplicate module/vendor copies that could double-link the package.","Avoid manual tools.Register calls for types already registered by init()."],"exampleFix":"// before\nconst resourceType string = \"dataplex-discover-metadata\" // registered twice\n// after\nconst resourceType string = \"dataplex-discover-metadata\" // single declaration retained; duplicate deleted","handlingStrategy":"validation","validationCode":"const want = \"dataplex-discover-metadata\"\n// pre-change uniqueness check:\n//   git grep -n 'dataplex-discover-metadata' -- '*.go'\n// exactly one const declaration keeps registration safe.","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"cannot start: %v\", r) // surfaces \"tool type already registered\" at boot\n    }\n}()","preventionTips":["Declare resourceType once per tool package only.","Grep for the intended key before creating a new dataplex tool.","Leave all registration to package init().","Keep a single copy of the module in the build graph.","Add CI checks that fail on duplicate registry keys or startup panics."],"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"}