googleapis/mcp-toolbox · error
tool type %q already registered
Error message
tool type %q already registered
What it means
This panic comes from the package-level init() of the postgres-long-running-transactions tool package. tools.Register() stores tool constructors in a global registry keyed by type string; returning false means "postgres-long-running-transactions" was already registered, so init() panics. The failure happens at process startup, before any YAML tool config is decoded.
Source
Thrown at internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions.go:62
wait_event_type,
wait_event,
query
FROM
pg_stat_activity
WHERE
state <> 'idle'
AND (now() - xact_start) > COALESCE($1::INTERVAL, interval '5 minutes')
AND xact_start IS NOT NULL
AND pid <> pg_backend_pid()
ORDER BY
xact_age DESC
LIMIT
COALESCE($2::int, 20);
`
func init() {
if !tools.Register(resourceType, newConfig) {
panic(fmt.Sprintf("tool type %q already registered", resourceType))
}
}
func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) {
actual := Config{ConfigBase: tools.ConfigBase{Name: name}}
if err := decoder.DecodeContext(ctx, &actual); err != nil {
return nil, err
}
return actual, nil
}
type compatibleSource interface {
PostgresPool() *pgxpool.Pool
RunSQL(context.Context, string, []any) (any, error)
}
type Config struct {
tools.ConfigBase `yaml:",inline"`View on GitHub (pinned to 8cc6e09de2)
Solutions
- Search the tree for "postgres-long-running-transactions" and remove or rename the second registration.
- Change the resourceType in any copied package to a unique value.
- Deduplicate go.mod replaces / vendor copies and rebuild with a clean cache.
- Confirm via fresh checkout that local edits are not introducing the collision.
Example fix
// before const resourceType string = "postgres-long-running-transactions" // duplicated // after // stock package unchanged; new package: const resourceType string = "postgres-stuck-transactions"
Defensive patterns
Strategy: validation
Validate before calling
// Validate uniqueness before launching the server:
const key = "postgres-long-running-transactions"
if countRegistrations(key) != 1 { // from your build-time registry scan
return fmt.Errorf("expected exactly one registration for %q", key)
} Type guard
func uniqueKey(rt string, all map[string][]string) string {
if len(all[rt]) > 1 {
panic("duplicate resourceType: " + strings.Join(all[rt], ", "))
}
return rt
} Try / catch
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "startup panic, check for duplicate tool registration: %v\n", r)
os.Exit(1)
}
}()
// server startup that links tool packages
} Prevention
- Rename resourceType immediately when template-copying a tool package.
- Run unit tests (`go test ./internal/tools/...`) which exercise init and surface duplicate panics early.
- Keep tool packages under a single import path; avoid module replace tricks that duplicate them.
- Grep for the intended key before assigning it to a new tool.
When it happens
Trigger: Linking a binary where two packages register "postgres-long-running-transactions": a duplicated postgreslongrunningtransactions package under a second import path, or an edited resourceType in another package colliding with it (postgreslongrunningtransactions.go:30).
Common situations: Copying the long-running-transactions tool as a template and forgetting to change resourceType; fork/vendor duplication; merge conflicts leaving two inits; internal forks that register a patched version alongside upstream.
Related errors
- tool type %q already registered
- tool type %q already registered
- tool type %q already registered
- tool type %q already registered
- tool type %q already registered
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/09f60dd59d7f96f8.
Report an issue: GitHub.