{"record":{"id":"7c8636fbdede3dce","repo":"googleapis/mcp-toolbox","slug":"tool-type-q-already-registered-7c8636","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/neo4j/neo4jexecutecypher/neo4jexecutecypher.go","lineNumber":33,"sourceCode":"package neo4jexecutecypher\n\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/util\"\n\t\"github.com/googleapis/mcp-toolbox/internal/util/parameters\"\n)\n\nconst resourceType string = \"neo4j-execute-cypher\"\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\tNeo4jDatabase() string // kept to ensure neo4j source\n\tRunQuery(context.Context, string, map[string]any, bool, bool) (any, error)\n}\n\ntype Config struct {\n\ttools.ConfigBase `yaml:\",inline\"`","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher.go#L15-L51","documentation":"This is a fail-fast panic raised during package initialization. The neo4jexecutecypher package registers its factory under resourceType \"neo4j-execute-cypher\" in the global toolRegistry via tools.Register() (internal/tools/tools.go:43). When the registry map already contains that key, Register() returns false and init() panics so duplicate tool-type claims crash at startup instead of silently overriding config decoding.","triggerScenarios":"A second init() registers \"neo4j-execute-cypher\": typically a copied/forked version of this package kept in the tree, the same package reached via two import paths, or a custom tool reusing this type string.","commonSituations":"Template-copying neo4jexecutecypher for a new write-path tool without changing the const; a branch merge that resurrects a deleted duplicate package; go.mod replace pulling old and new module versions simultaneously.","solutions":["grep -rn 'neo4j-execute-cypher' to find both init() registrations; make the new tool's resourceType unique.","Remove the duplicate import (cmd/root.go) or delete the obsolete package.","Run go mod tidy and audit replace directives for duplicate module copies.","Rebuild and run `go test ./internal/tools/neo4j/...`."],"exampleFix":"// before\ncopied package kept: const resourceType string = \"neo4j-execute-cypher\"\n\n// after\nconst resourceType string = \"neo4j-execute-cypher-batch\" // unique to the new tool","handlingStrategy":"validation","validationCode":"// Verify uniqueness before building:\n// grep -rn '\"neo4j-execute-cypher\"' --include='*.go' . | grep 'resourceType\\|tools.Register'\n// Exactly one match expected. Soft guard for custom tools:\nfunc init() {\n\tif !tools.Register(resourceType, newConfig) {\n\t\tfmt.Printf(\"WARNING: %s already registered; skipping duplicate init\\n\", resourceType)\n\t\treturn\n\t}\n}","typeGuard":"func isRegistered(resourceType string) bool {\n\t_, exists := registrySnapshot[resourceType]\n\treturn exists\n}","tryCatchPattern":"// Recover at the process boundary:\nfunc main() {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tif s, ok := r.(string); ok && strings.Contains(s, \"already registered\") {\n\t\t\t\tlog.Fatalf(\"duplicate tool registration: %s\", s)\n\t\t\t}\n\t\t\tpanic(r)\n\t\t}\n\t}()\n\trootCmd.Execute()\n}","preventionTips":["When copying a tool package, change resourceType before writing any other code.","Add a uniqueness unit test over the tool registry to catch duplicates in CI.","Audit cmd/root.go imports after merges for resurrected duplicate packages.","Avoid duplicate replace/vendor directives that link the same package twice.","Run go build ./... locally before opening a PR touching registrations."],"tags":["go","init-panic","tool-registry","duplicate-registration","neo4j"],"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"}