{"record":{"id":"df9dbbfaa49b9aa9","repo":"googleapis/mcp-toolbox","slug":"tool-type-q-already-registered-df9dbb","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/postgres/postgreslistactivequeries/postgreslistactivequeries.go","lineNumber":58,"sourceCode":"        wait_event_type,\n        wait_event,\n        backend_start,\n        xact_start,\n        query_start,\n        now() - query_start AS query_duration,\n        query\n    FROM pg_stat_activity\n    WHERE state = 'active'\n        AND backend_type = 'client backend'\n        AND ($1::INTERVAL IS NULL OR now() - query_start >= $1::INTERVAL)\n        AND ($2::text IS NULL OR application_name NOT IN (SELECT trim(app) FROM unnest(string_to_array($2, ',')) AS app))\n    ORDER BY query_duration DESC\n    LIMIT COALESCE($3::int, 50);\n`\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\tPostgresPool() *pgxpool.Pool\n\tRunSQL(context.Context, string, []any) (any, error)\n}\n\ntype Config struct {\n\ttools.ConfigBase `yaml:\",inline\"`","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries.go#L40-L76","documentation":"This is a startup panic from postgreslistactivequeries' init(): tools.Register (internal/tools/tools.go:43) returned false, meaning another package already registered a factory under the same resourceType string (\"postgres-list-active-queries\") in the shared toolRegistry map. Since tool YAML configs resolve by `type` string, a duplicate would be ambiguous, so the binary panics during init before serving.","triggerScenarios":"Importing a second package whose init() registers \"postgres-list-active-queries\" — typically a copy-pasted postgreslistactivequeries.go with an unchanged `resourceType` constant — or two files in the build declaring the same constant.","commonSituations":"Cloning the tool to add filters or a different LIMIT default while renaming only the package; a merge resolution that kept duplicate directories; importing a forked/vendored variant alongside the original in a custom toolbox build.","solutions":["Locate the second registration via rg '\"postgres-list-active-queries\"' internal/ cmd/ and make one `resourceType` unique.","For an intentional variant, rename the constant (and package) to a new kebab-case type such as \"postgres-list-active-queries-extended\".","Remove the duplicate package/import if it is dead code.","Verify startup with `go build ./...` and unit tests."],"exampleFix":"// before (copied variant)\nconst resourceType string = \"postgres-list-active-queries\"\n// after\nconst resourceType string = \"postgres-list-active-queries-extended\"","handlingStrategy":"validation","validationCode":"// Uniqueness check before build/CI:\n//   rg -F '\"postgres-list-active-queries\"' internal/ cmd/  # expect exactly 1 hit\n// Smoke test linking all tool packages:\nfunc TestToolRegistryInit(t *testing.T) {\n\t// panics on duplicate registration; must pass\n}","typeGuard":"func typeStringAppearsOnce(root, resourceType string) bool {\n\treturn countLiterals(root, \"\\\"\"+resourceType+\"\\\"\") == 1\n}","tryCatchPattern":null,"preventionTips":["Rename `resourceType` in the same commit when copying a tool into a new package.","Keep `resourceType` identical to the tool's kebab-case name and folder name.","Add an init-touching smoke test to CI to catch duplicate registrations early.","Grep the type string before importing any new tool package.","Prune dead/forked copies of tools from the module."],"tags":["go","init-panic","duplicate-registration","tool-registry","postgres"],"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"}