googleapis/mcp-toolbox · error

unable to retrieve source %q for tool %q

Error message

unable to retrieve source %q for tool %q

What it means

After a tool initializes successfully, initializeTools looks up the tool's declared source (t.GetSourceName()) in the initialized sourcesMap. If the source name is not found and source validation is enabled (SkipSourceValidation is false), startup fails because the tool points at a source that does not exist in the config.

Source

Thrown at internal/server/server.go:295

		var src sources.Source
		t, err := func() (tools.Tool, error) {
			_, span := instrumentation.Tracer.Start(
				ctx,
				"toolbox/server/tool/init",
				trace.WithAttributes(attribute.String("tool_type", tc.ToolConfigType())),
				trace.WithAttributes(attribute.String("tool_name", name)),
			)
			defer span.End()
			t, err := tc.Initialize(ctx)
			if err != nil {
				return nil, fmt.Errorf("unable to initialize tool %q: %w", name, err)
			}

			if srcName := t.GetSourceName(); srcName != "" && sourcesMap != nil {
				var ok bool
				src, ok = sourcesMap[srcName]
				if !ok && !cfg.SkipSourceValidation {
					return nil, fmt.Errorf("unable to retrieve source %q for tool %q", srcName, name)
				}
			}

			if !cfg.SkipSourceValidation {
				err = t.ValidateSource(src)
				if err != nil {
					return nil, err
				}
			}
			return t, nil
		}()
		if err != nil {
			return nil, err
		}

		if tools.ShouldSuppress(ctx, t, src) {
			continue
		}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Add or fix the `source:` reference in the tool config to match an existing key under `sources:`.
  2. List your sources section and confirm the exact spelling/case of the key.
  3. If the source intentionally varies per environment, template the config (envsubst) so names stay consistent.

Example fix

// before (tools.yml)
tools:
  search_users:
    kind: postgres-sql
    source: postgress  # typo

// after
sources:
  postgres:
    kind: postgres
    uri: ...
tools:
  search_users:
    kind: postgres-sql
    source: postgres
Defensive patterns

Strategy: validation

Validate before calling

sources := cfg.Sources // map[string]SourceConfig
for name, tc := range cfg.ToolConfigs {
    if src := tc.SourceName(); src != "" {
        if _, ok := sources[src]; !ok {
            return fmt.Errorf("tool %q references unknown source %q", name, src)
        }
    }
}

Type guard

func sourceExists(cfg server.ServerConfig, name string) bool {
    _, ok := cfg.Sources[name]
    return ok
}

Try / catch

if _, err := server.NewServer(ctx, cfg); err != nil {
    var src, tool string
    if _, e := fmt.Sscanf(err.Error(), "unable to retrieve source %q for tool %q", &src, &tool); e == nil {
        log.Printf("add or fix source %q used by tool %q", src, tool)
    }
    return err
}

Prevention

When it happens

Trigger: A tool entry in the config declares `source: some_name` but no source with that key exists under `sources:` in tools.yml, and the server is started normally (not the offline path, which sets SkipSourceValidation=true).

Common situations: Renamed or deleted source entries while tools still reference the old name, typos in the source key (map keys are case-sensitive), or copy-pasting tools between config files whose sources differ.

Related errors


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