googleapis/mcp-toolbox · critical

tool type %q already registered

Error message

tool type %q already registered

What it means

This panic is thrown by init() in internal/tools/dataplex/dataplexcreatedataproduct when tools.Register for "dataplex-create-data-product" finds the key already registered and returns false. The registry intentionally refuses duplicate tool types, and the package panics at startup to make the conflict impossible to miss. Each tool type key must appear exactly once in the binary.

Source

Thrown at internal/tools/dataplex/dataplexcreatedataproduct/dataplexcreatedataproduct.go:34

import (
	"context"
	"fmt"
	"net/http"

	yaml "github.com/goccy/go-yaml"
	"github.com/googleapis/mcp-toolbox/internal/sources"
	"github.com/googleapis/mcp-toolbox/internal/sources/dataplex"
	"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 = "dataplex-create-data-product"

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 {
	CreateDataProduct(
		ctx context.Context,
		locationId string,
		dataProductId string,
		displayName string,
		description string,

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Grep for "dataplex-create-data-product" and remove/rename the duplicate resourceType declaration.
  2. Maintain one unique resourceType const per tool package.
  3. Verify a single copy of the package is linked (go.mod, vendor).
  4. In tests, rely on init() and avoid re-registering existing types.

Example fix

// before
const resourceType string = "dataplex-create-data-product" // conflicts with existing registration
// after
const resourceType string = "dataplex-create-data-product" // declared once; duplicate removed
Defensive patterns

Strategy: validation

Validate before calling

const want = "dataplex-create-data-product"
// verify before building:
//   git grep -n '"dataplex-create-data-product"' -- '*.go'
// a single declaration site is required to avoid the panic.

Try / catch

func init() {
    defer func() {
        if r := recover(); r != nil {
            log.Fatalf("tool %s registration conflict: %v", resourceType, r)
        }
    }()
    tools.Register(resourceType, newConfig)
}

Prevention

When it happens

Trigger: A second init() registers the same "dataplex-create-data-product" const (duplicate declaration or double-linked package); or a test/bootstrap path calls tools.Register after init already registered the type.

Common situations: Cloned dataplex tool with unchanged resourceType; merge conflict resolution keeping both registrations; vendored duplicates of the module; test helpers that re-run registration logic.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/33ae436af4ab875f. Report an issue: GitHub.