googleapis/mcp-toolbox · critical
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 serverlesssparkcreatesparkbatch tool. MCP Toolbox keeps a global registry of tool types keyed by a resource type string; tools.Register returns false if the key already exists, and the package deliberately panics to signal a duplicate registration. It is a programming/registration error, not a runtime failure users can trigger.
Source
Thrown at internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go:32
package serverlesssparkcreatesparkbatch
import (
"context"
"fmt"
dataproc "cloud.google.com/go/dataproc/v2/apiv1/dataprocpb"
"github.com/goccy/go-yaml"
"github.com/googleapis/mcp-toolbox/internal/tools"
"github.com/googleapis/mcp-toolbox/internal/tools/serverlessspark/createbatch"
"github.com/googleapis/mcp-toolbox/internal/util/parameters"
)
const resourceType = "serverless-spark-create-spark-batch"
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) {
baseCfg, err := createbatch.NewConfig(ctx, name, decoder)
if err != nil {
return nil, err
}
return Config{Config: baseCfg}, nil
}
type Config struct {
createbatch.Config
ScopesRequired []string `yaml:"scopesRequired"`
}
// validate interfaceView on GitHub (pinned to 8cc6e09de2)
Solutions
- Search the codebase for the duplicate resourceType string and change it so each tool registers a unique constant
- Check go.mod / vendor/ for a duplicated import path of the same tools package and remove one copy
- If a renamed package should replace an old one, remove the old package's init() registration or delete the old package
- Rebuild with `go build -o toolbox` and run `go test ./internal/tools/...` to confirm the panic is gone
Example fix
// before const resourceType = "serverless-spark-create-spark-batch" // duplicate in two packages // after const resourceType = "serverless-spark-create-spark-batch-v2" // unique per registering package (or delete the duplicate package)
Defensive patterns
Strategy: validation
Validate before calling
// before importing/registering, ensure uniqueness grep -rn 'serverless-spark-create-spark-batch' internal/ tools/ # expect exactly one hit // or in Go: guard tests tools.Register(resourceType, newConfig) // write a test asserting each resourceType registers exactly once
Prevention
- Keep resourceType constants unique per package and derive them from the tool's canonical name
- Add a CI test that imports all tools packages and asserts no duplicate registrations
- Avoid vendoring or forking packages under internal/tools
- When renaming tools, delete the old package instead of leaving both registered
When it happens
Trigger: Two Go packages register the same resourceType string "serverless-spark-create-spark-batch", or the same package is linked twice under different import paths (e.g. vendored copy plus module copy), causing init() to run twice against the same registry.
Common situations: Copy-pasting a tool package and forgetting to change resourceType; accidentally importing a duplicated/forked copy of internal/tools; renaming a package but keeping the old const, colliding with the original that is still imported.
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/40cdf51cb1c9874a.
Report an issue: GitHub.