{"record":{"id":"dcb6191f3e7148c5","repo":"googleapis/mcp-toolbox","slug":"invalid-s-parameter-expected-a-string","errorCode":null,"errorMessage":"invalid '%s' parameter; expected a string","messagePattern":"invalid '(.+?)' parameter; expected a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/cloudhealthcare/common/util.go","lineNumber":83,"sourceCode":"\t\t\tif _, ok := v.([]any); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid '%s' parameter; expected a string array\", k)\n\t\t\t}\n\t\t\tattributeIDsSlice, err := parameters.ConvertAnySliceToTyped(v.([]any), \"string\")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"can't convert '%s' to array of strings: %s\", k, err)\n\t\t\t}\n\t\t\tattributeIDs := attributeIDsSlice.([]string)\n\t\t\tif len(attributeIDs) != 0 {\n\t\t\t\topts = append(opts, googleapi.QueryParameter(k, strings.Join(attributeIDs, \",\")))\n\t\t\t}\n\t\t} else if k == EnablePatientNameFuzzyMatchingKey {\n\t\t\tif _, ok := v.(bool); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid '%s' parameter; expected a boolean\", k)\n\t\t\t}\n\t\t\topts = append(opts, googleapi.QueryParameter(k, fmt.Sprintf(\"%t\", v.(bool))))\n\t\t} else if slices.Contains(paramKeys, k) {\n\t\t\tif _, ok := v.(string); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid '%s' parameter; expected a string\", k)\n\t\t\t}\n\t\t\tif v.(string) != \"\" {\n\t\t\t\topts = append(opts, googleapi.QueryParameter(k, v.(string)))\n\t\t\t}\n\t\t}\n\t}\n\treturn opts, nil\n}\n","sourceCodeStart":65,"sourceCodeEnd":92,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/cloudhealthcare/common/util.go#L65-L92","documentation":"Every other recognized DICOM search parameter (keys listed in paramKeys, e.g. patient name, date ranges) must be a string. If a value arrives as a number, bool, array or object, the assertion fails and this error is returned.","triggerScenarios":"Invoking a DICOM search tool with a search parameter (one of paramKeys) whose value is not a string, e.g. {\"limit\": 10} on a string-typed key or a numeric patient ID.","commonSituations":"LLM sending unquoted numbers or dates as JSON numbers; clients serializing dates as timestamps instead of DICOM date strings (e.g. \"19991231\"); mixed payloads from dynamic UIs.","solutions":["Quote the value so it is a JSON string, e.g. \"19991231-20201231\".","Convert numbers to their DICOM string representation before sending.","Check the tool's parameter schema for which keys expect strings.","Validate payload types before invoking."],"exampleFix":"// before\n{\"studydate\": 20201231}\n// after\n{\"studydate\": \"20201231\"}","handlingStrategy":"validation","validationCode":"function assertStringParams(obj, keys) {\n  for (const k of keys) {\n    if (k in obj && typeof obj[k] !== 'string') {\n      throw new Error(`parameter ${k} must be a string`);\n    }\n  }\n}\n// e.g. assertStringParams(params, ['patientid','studydate','modality'])","typeGuard":"function isString(v) { return typeof v === 'string'; }","tryCatchPattern":null,"preventionTips":["Format dates as DICOM strings (YYYYMMDD) before sending","Never rely on JSON numbers for string-typed search params","Validate payloads against the tool's declared parameter schema","Wrap LLM tool-call arguments in a type-checking adapter"],"tags":["go","parameter-validation","dicom","type-mismatch"],"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"}