{"record":{"id":"9d71a4bebccad4e4","repo":"googleapis/mcp-toolbox","slug":"header-param-s-got-value-of-type-t-not-string","errorCode":null,"errorMessage":"header param %s got value of type %t, not string","messagePattern":"header param (.+?) got value of type %t, not string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/http/http.go","lineNumber":264,"sourceCode":"\t\t}\n\t\tquery.Add(p.GetName(), fmt.Sprintf(\"%v\", v))\n\t}\n\tparsedURL.RawQuery = query.Encode()\n\treturn parsedURL.String(), nil\n}\n\n// Helper function to generate the HTTP headers upon Tool invocation.\nfunc getHeaders(headerParams parameters.Parameters, defaultHeaders map[string]string, paramsMap map[string]any) (map[string]string, error) {\n\t// Populate header params\n\tallHeaders := make(map[string]string)\n\tmaps.Copy(allHeaders, defaultHeaders)\n\tfor _, p := range headerParams {\n\t\theaderValue, ok := paramsMap[p.GetName()]\n\t\tif ok {\n\t\t\tif strValue, ok := headerValue.(string); ok {\n\t\t\t\tallHeaders[p.GetName()] = strValue\n\t\t\t} else {\n\t\t\t\treturn nil, fmt.Errorf(\"header param %s got value of type %t, not string\", p.GetName(), headerValue)\n\t\t\t}\n\t\t}\n\t}\n\treturn allHeaders, nil\n}\n\nfunc (t Tool) Invoke(ctx context.Context, s sources.Source, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {\n\tsource, ok := s.(compatibleSource)\n\tif !ok {\n\t\treturn nil, util.NewClientServerError(\"source used is not compatible with the tool\", http.StatusInternalServerError, nil)\n\t}\n\t// Combine Source and Tool headers.\n\t// In case of conflict, Tool header overrides Source header\n\tcombinedHeaders := make(map[string]string)\n\tmaps.Copy(combinedHeaders, source.HttpDefaultHeaders())\n\tmaps.Copy(combinedHeaders, t.Cfg.Headers)\n\n\tparamsMap := params.AsMap()","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/http/http.go#L246-L282","documentation":"HTTP header parameters must be supplied as JSON/YAML strings. getHeaders iterates the declared header parameters and errors when a provided value exists but is not a string (e.g. a number, boolean, object, or array), since HTTP header values must be text.","triggerScenarios":"Invoke is called with a header parameter set to a non-string JSON value, e.g. {\"X-Count\": 5} or {\"X-Flag\": true} or a nested object, for a parameter declared in headerParams.","commonSituations":"LLM tool callers emitting unquoted numbers/booleans for headers; clients passing integers for numeric-looking headers like X-Request-Id: 12345; YAML configs with unquoted values that parse as bool/int.","solutions":["Convert the value to a string before invoking (e.g. \"5\", \"true\", \"12345\")","Quote the value in YAML tool configs so it parses as a string","If the value comes from an LLM/model call, add instructions or schema constraints so header params are always emitted as strings"],"exampleFix":"// before\n{\"headers\": {\"X-Count\": 5}}\n// after\n{\"headers\": {\"X-Count\": \"5\"}}","handlingStrategy":"type-guard","validationCode":"for k, v := range headerArgs {\n    if _, ok := v.(string); !ok {\n        return fmt.Errorf(\"header %s must be a string, got %T\", k, v)\n    }\n}","typeGuard":"func allStrings(m map[string]any) bool {\n    for _, v := range m {\n        if _, ok := v.(string); !ok { return false }\n    }\n    return true\n}","tryCatchPattern":"headers, err := tool.Invoke(ctx, params)\nif err != nil && strings.Contains(err.Error(), \"got value of type\") {\n    // coerce values to strings and retry once\n}\nvar typeErr *json.UnmarshalTypeError // if parsing client-side, check this","preventionTips":["Quote numeric/boolean header values in YAML configs and JSON payloads","Declare header parameters with string-typed schemas so clients coerce automatically","Instruct LLM callers that header parameters must be strings"],"tags":["http","headers","type-error","parameters"],"backgroundTag":"parameter-type-mismatch","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"}