{"record":{"id":"9e0292abcc207168","repo":"googleapis/mcp-toolbox","slug":"tool-type-q-already-registered-9e0292","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/databaseinsights/getadvancedtimeserieswaiteventstats/getadvancedtimeserieswaiteventstats.go","lineNumber":34,"sourceCode":"\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\n\tyaml \"github.com/goccy/go-yaml\"\n\t\"github.com/googleapis/mcp-toolbox/internal/sources\"\n\t\"github.com/googleapis/mcp-toolbox/internal/sources/databaseinsights\"\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 = \"databaseinsights-get-advanced-time-series-wait-event-stats\"\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\tFetchWaitEventTimeSeries(ctx context.Context, req *databaseinsights.FetchWaitEventTimeSeriesRequest) (*databaseinsights.FetchWaitEventTimeSeriesResponse, error)\n}\n\ntype Config struct {\n\ttools.ConfigBase `yaml:\",inline\"`\n\tType             string                 `yaml:\"type\" validate:\"required\"`","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/databaseinsights/getadvancedtimeserieswaiteventstats/getadvancedtimeserieswaiteventstats.go#L16-L52","documentation":"This panic is raised by init() in internal/tools/databaseinsights/getadvancedtimeserieswaiteventstats because tools.Register was called with the resourceType \"databaseinsights-get-advanced-time-series-wait-event-stats\", which the registry already contains. tools.Register returns false on duplicate keys and the package panics to fail fast. It protects the invariant that each tool type maps to exactly one Config factory.","triggerScenarios":"Two init() paths register the same resourceType constant (duplicate declaration in another package/file), or a test utility invokes the registration function a second time after package initialization.","commonSituations":"Cloning a neighboring databaseinsights tool and forgetting to update the const; rebasing/merging that reintroduced an identical tool type; vendor or module duplication linking the package twice under different import paths.","solutions":["Grep for \"databaseinsights-get-advanced-time-series-wait-event-stats\" and remove/rename the duplicate resourceType.","Ensure the const is unique per tool package (kebab-case, source-prefixed).","Check go.mod/vendor for duplicate copies of the module that would double-link the package.","In test code, avoid re-registering types already registered by init()."],"exampleFix":"// before\nconst resourceType string = \"databaseinsights-get-advanced-time-series-wait-event-stats\" // conflicts with existing key\n// after\nconst resourceType string = \"databaseinsights-get-advanced-wait-event-timeseries\" // renamed unique key","handlingStrategy":"validation","validationCode":"const want = \"databaseinsights-get-advanced-time-series-wait-event-stats\"\n// Run before adding the tool:\n//   git grep -n 'databaseinsights-get-advanced-time-series-wait-event-stats' -- '*.go'\n// More than one `const resourceType` hit means the registration will panic.","typeGuard":null,"tryCatchPattern":"func safeRegister() (recovered any) {\n    defer func() { recovered = recover() }()\n    tools.Register(resourceType, newConfig)\n    return nil\n}\n// at startup: if r := safeRegister(); r != nil { log.Fatalf(\"registry conflict: %v\", r) }","preventionTips":["Keep one canonical resourceType declaration per tool package.","Search the registry keys before choosing a new tool type name.","Do not manually invoke registration helpers that init() already runs.","Pin module versions to prevent duplicate package copies.","Enforce uniqueness with a unit test that asserts every registered key appears once."],"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"}