{"record":{"id":"9bd1da9eee13d8d5","repo":"googleapis/mcp-toolbox","slug":"unable-to-parse-tool-q-as-type-q-w","errorCode":null,"errorMessage":"unable to parse tool %q as type %q: %w","messagePattern":"unable to parse tool %q as type %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/tools.go","lineNumber":63,"sourceCode":"\t\t// Tool with this type already exists, do not overwrite.\n\t\treturn false\n\t}\n\ttoolRegistry[resourceType] = factory\n\treturn true\n}\n\nvar ErrUnknownToolType = fmt.Errorf(\"unknown tool type\")\n\n// DecodeConfig looks up the registered factory for the given type and uses it\n// to decode the tool configuration.\nfunc DecodeConfig(ctx context.Context, resourceType string, name string, decoder *yaml.Decoder) (ToolConfig, error) {\n\tfactory, found := toolRegistry[resourceType]\n\tif !found {\n\t\treturn nil, fmt.Errorf(\"%w: %q\", ErrUnknownToolType, resourceType)\n\t}\n\ttoolConfig, err := factory(ctx, name, decoder)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to parse tool %q as type %q: %w\", name, resourceType, err)\n\t}\n\treturn toolConfig, nil\n}\n\ntype ToolConfig interface {\n\tToolConfigType() string\n\tInitialize(context.Context) (Tool, error)\n}\n\n// https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations\ntype ToolAnnotations struct {\n\tDestructiveHint *bool `json:\"destructiveHint,omitempty\" yaml:\"destructiveHint,omitempty\"`\n\tIdempotentHint  *bool `json:\"idempotentHint,omitempty\" yaml:\"idempotentHint,omitempty\"`\n\tOpenWorldHint   *bool `json:\"openWorldHint,omitempty\" yaml:\"openWorldHint,omitempty\"`\n\tReadOnlyHint    *bool `json:\"readOnlyHint,omitempty\" yaml:\"readOnlyHint,omitempty\"`\n}\n\n// NewReadOnlyAnnotations creates default annotations for a read-only tool.","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/tools.go#L45-L81","documentation":"After DecodeConfig finds the factory for the tool type, it invokes the factory to parse the tool's YAML block. If that factory returns an error, it is wrapped with this message naming the tool and the type. This means the tool's kind was valid but the tool-specific configuration could not be parsed or initialized.","triggerScenarios":"Any registered factory (e.g. trinoexecutesql's Config.Initialize reached through the YAML decoder) returns an error — bad fields, missing required values like description, invalid parameter definitions — while decoding a tool named <name> as type <resourceType>.","commonSituations":"Missing required fields (e.g. `description`), malformed parameter definitions, invalid YAML structure inside the tool block, source names that fail validation during Initialize.","solutions":["Read the wrapped cause at the end of the error chain for the underlying problem (e.g. \"description is required for tool \\\"x\\\"\")","Fix the offending field in the named tool's YAML block","Validate required fields for the tool type per its documentation","Run the config through a YAML linter to catch structural issues"],"exampleFix":"// before (tools.yaml)\nmy-tool:\n  kind: trino-execute-sql\n  source: my-trino\n// after\nmy-tool:\n  kind: trino-execute-sql\n  source: my-trino\n  description: Runs a SQL query against Trino","handlingStrategy":"validation","validationCode":"// Before parsing, check required fields for each tool block\nfor name, t := range toolsRaw {\n    if t[\"description\"] == \"\" {\n        return fmt.Errorf(\"tool %q: description is required\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":"toolConfig, err := tools.DecodeConfig(ctx, kind, name, dec)\nif err != nil {\n    var pe *fmt.WrapError // or inspect the chain\n    log.Printf(\"tool %q (kind %q) rejected: %v\", name, kind, err)\n    return fmt.Errorf(\"config error in tool %q: %w\", name, err)\n}","preventionTips":["Always include description for every tool in tools.yaml","Validate the full config with a dry-run/decode before deploying","Keep tool YAML blocks minimal and copied from docs","Read the whole error chain, not just the wrapper message"],"tags":["go","config","yaml","tool-parsing"],"backgroundTag":"tool-config-parse-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}