googleapis/mcp-toolbox · error

error unmarshaling %s: %w

Error message

error unmarshaling %s: %w

What it means

Single-document variant of the unmarshaling failure: when the YAML file contains only one document, UnmarshalPrimitiveConfig returns 'error unmarshaling <kind>: <cause>' without document-index decoration. The wrapped cause from UnmarshalYAMLSourceConfig / UnmarshalYAMLToolConfig / etc. holds the actual decoding error.

Source

Thrown at internal/server/config.go:238

				fallbackToken := keyToken(doc.Body, "name")
				if fallbackToken == nil {
					fallbackToken = keyToken(doc.Body, "kind")
				}
				return nil, nil, nil, nil, nil, nil, fmt.Errorf("%s missing 'name' field or it is not a string", formatDocLocation(docIndex, fallbackToken, doc.Body))
			}
			return nil, nil, nil, nil, nil, nil, fmt.Errorf("missing 'name' field or it is not a string")
		}
		// remove 'kind' from map for strict unmarshaling
		delete(resource, "kind")

		switch kind {
		case "source":
			c, err := UnmarshalYAMLSourceConfig(ctx, name, resource)
			if err != nil {
				if len(file.Docs) > 1 {
					return nil, nil, nil, nil, nil, nil, fmt.Errorf("document %d: error unmarshaling %s %q: %w", docIndex, kind, name, err)
				}
				return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %w", kind, err)
			}
			if sourceConfigs == nil {
				sourceConfigs = make(SourceConfigs)
			}
			if _, exists := sourceConfigs[name]; exists {
				return nil, nil, nil, nil, nil, nil, fmt.Errorf("source %q declared more than once", name)
			}
			sourceConfigs[name] = c
		case "authService":
			c, err := UnmarshalYAMLAuthServiceConfig(ctx, name, resource)
			if err != nil {
				if len(file.Docs) > 1 {
					return nil, nil, nil, nil, nil, nil, fmt.Errorf("document %d: error unmarshaling %s %q: %w", docIndex, kind, name, err)
				}
				return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %w", kind, err)
			}
			if authServiceConfigs == nil {
				authServiceConfigs = make(AuthServiceConfigs)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Inspect the wrapped cause after the colon for the exact offending field.
  2. Correct the key spelling or value type in the YAML.
  3. Validate against the documented schema for that kind.
  4. Upgrade/downgrade alignment: check release notes for schema changes to that kind.

Example fix

// before
kind: tool
name: t
source: mysource
description: 42
// after
kind: tool
name: t
source: mysource
description: my tool
Defensive patterns

Strategy: validation

Validate before calling

var probe map[string]any
if err := yaml.Unmarshal([]byte(cfgText), &probe); err != nil { return err }
// ensure every key maps to the documented type before handing to ParseConfig
for field, v := range probe {
    _ = field
    _ = v
}
// then run the real parse to catch strict-unmarshal issues early
if _, _, _, _, _, _, err := server.ParseConfig(ctx, params); err != nil {
    return fmt.Errorf("config parse failed: %w", err)
}
return nil

Try / catch

if err := parseAndValidate(cfgText); err != nil {
    cause := err
    for errors.Unwrap(cause) != nil { cause = errors.Unwrap(cause) }
    log.Fatalf("single-doc unmarshal failure — fix the root cause: %v", cause)
}

Prevention

When it happens

Trigger: ParseConfig on a single-document YAML whose resource map fails strict decoding into the config struct for its kind (unknown fields, wrong value types, invalid nested configs).

Common situations: Typo'd keys in a standalone tools.yaml; passing a string where a list is expected; using a prebuilt-config field that no longer exists after upgrade.

Related errors


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