{"record":{"id":"9b0082d0ff819514","repo":"googleapis/mcp-toolbox","slug":"tool-type-q-already-registered-9b0082","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/dataform/dataformcompilelocal/dataformcompilelocal.go","lineNumber":34,"sourceCode":"\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\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/util\"\n\t\"github.com/googleapis/mcp-toolbox/internal/util/parameters\"\n)\n\nconst resourceType string = \"dataform-compile-local\"\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 Config struct {\n\ttools.ConfigBase `yaml:\",inline\"`\n\tType             string                 `yaml:\"type\" validate:\"required\"`\n\tAnnotations      *tools.ToolAnnotations `yaml:\"annotations,omitempty\"`\n}\n\nvar _ tools.ToolConfig = Config{}","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal.go#L16-L52","documentation":"This panic is thrown by init() in internal/tools/dataform/dataformcompilelocal because tools.Register for resourceType \"dataform-compile-local\" found the key already present in the tool registry and returned false. The library fails fast at startup rather than allowing one tool config factory to overwrite another. The remedy is a single, unique registration for this tool type per process.","triggerScenarios":"Another file/package declares the same \"dataform-compile-local\" const and its init() also registers it; or test/bootstrap code calls tools.Register again for the same key after package init already did.","commonSituations":"Renaming a tool package but keeping the old resourceType that already exists; merging two branches that both add dataform-compile-local; tests that exercise registration explicitly while init has already run.","solutions":["Grep for \"dataform-compile-local\" and remove or rename the duplicate resourceType.","Keep one source of truth for the tool type key in the dataformcompilelocal package.","Run `go build ./...` and unit tests to confirm only one registration executes.","Avoid calling tools.Register manually in tests for types registered by init()."],"exampleFix":"// before\nconst resourceType string = \"dataform-compile-local\" // duplicate declaration elsewhere\n// after\nconst resourceType string = \"dataform-compile-local\" // only in dataformcompilelocal.go; duplicate deleted","handlingStrategy":"validation","validationCode":"const want = \"dataform-compile-local\"\n// before adding/renaming the tool, run:\n//   git grep -n '\"dataform-compile-local\"' -- '*.go'\n// exactly one const declaration is required.","typeGuard":null,"tryCatchPattern":"func mustRegister(key string, fn func(context.Context, string, *yaml.Decoder) (tools.ToolConfig, error)) {\n    defer func() {\n        if r := recover(); r != nil {\n            log.Fatalf(\"tool %s: %v\", key, r)\n        }\n    }()\n    if !tools.Register(key, fn) {\n        log.Fatalf(\"tool %s already registered\", key)\n    }\n}","preventionTips":["Keep the resourceType const declared only in the tool's own file.","Grep for the key before introducing a new or renamed tool.","Never call tools.Register outside package init().","Ensure go.mod/vendor contains a single copy of the module.","Run unit tests that exercise all init() registrations in CI."],"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"}