googleapis/mcp-toolbox · critical
tool type %q already registered
Error message
tool type %q already registered
What it means
This is a fail-fast panic raised during package initialization. The oceanbaseexecutesql package registers its factory under resourceType "oceanbase-execute-sql" in the global toolRegistry via tools.Register() (internal/tools/tools.go:43). When the registry map already holds that key (Register returns false), init() panics so duplicate tool-type claims are caught immediately at startup instead of one factory silently shadowing the other.
Source
Thrown at internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql.go:34
import (
"context"
"database/sql"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/mcp-toolbox/internal/sources"
"github.com/googleapis/mcp-toolbox/internal/tools"
"github.com/googleapis/mcp-toolbox/internal/util"
"github.com/googleapis/mcp-toolbox/internal/util/parameters"
)
const resourceType string = "oceanbase-execute-sql"
func init() {
if !tools.Register(resourceType, newConfig) {
panic(fmt.Sprintf("tool type %q already registered", resourceType))
}
}
type compatibleSource interface {
OceanBasePool() *sql.DB
RunSQL(context.Context, string, []any) (any, error)
}
type Config struct {
tools.ConfigBase `yaml:",inline"`
Type string `yaml:"type" validate:"required"`
Source string `yaml:"source" validate:"required"`
Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"`
}
// validate interface
var _ tools.ToolConfig = Config{}
View on GitHub (pinned to 8cc6e09de2)
Solutions
- grep -rn 'oceanbase-execute-sql' to locate both registrations; assign the duplicate a unique resourceType.
- Remove the duplicate import or delete the obsolete package copy.
- Run go mod tidy and check replace directives / vendor for duplicates.
- Verify with `go build ./...` and `go test ./internal/tools/oceanbase/...`.
Example fix
// before copied package: const resourceType string = "oceanbase-execute-sql" // after const resourceType string = "oceanbase-execute-sql-readonly" // unique to the new tool
Defensive patterns
Strategy: validation
Validate before calling
// Verify uniqueness before building:
// grep -rn '"oceanbase-execute-sql"' --include='*.go' . | grep 'resourceType\|tools.Register'
// Exactly one match expected. Soft guard for custom tools:
func init() {
if !tools.Register(resourceType, newConfig) {
fmt.Printf("WARNING: %s already registered; skipping duplicate init\n", resourceType)
return
}
} Type guard
func isRegistered(resourceType string) bool {
_, exists := registrySnapshot[resourceType]
return exists
} Try / catch
// Recover at the process boundary:
func main() {
defer func() {
if r := recover(); r != nil {
if s, ok := r.(string); ok && strings.Contains(s, "already registered") {
log.Fatalf("duplicate tool registration: %s", s)
}
panic(r)
}
}()
rootCmd.Execute()
} Prevention
- Rename resourceType, package, and directory together when deriving a new OceanBase tool from an existing one.
- Add a CI test asserting all registered resourceType values are unique.
- After rebases or merges, run go build ./... to surface duplicate registrations immediately.
- Keep go.mod free of overlapping replace/vendor copies of the module.
- grep the type string before committing changes to tool packages.
When it happens
Trigger: Another init() calls tools.Register("oceanbase-execute-sql", ...): a copy of this package left after a rename, the package imported under two module paths (replace/fork/vendor), or a custom tool reusing this type string.
Common situations: Template-copying oceanbaseexecutesql for a new OceanBase tool and leaving the const unchanged; a rebase duplicating the package directory; two versions of the toolbox module both linked into the binary.
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/1d42c9eaffe7dad0.
Report an issue: GitHub.