{"record":{"id":"4bfd4c220b48f564","repo":"googleapis/mcp-toolbox","slug":"scopesrequired-must-be-a-list-of-strings","errorCode":null,"errorMessage":"scopesRequired must be a list of strings","messagePattern":"scopesRequired must be a list of strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/server/config.go","lineNumber":485,"sourceCode":"\t\treturn nil, fmt.Errorf(\"`authRequired` and `useClientOAuth` are mutually exclusive. Choose only one authentication method\")\n\t}\n\t// Make `authRequired` an empty list instead of nil for Tool manifest\n\tif r[\"authRequired\"] == nil {\n\t\tr[\"authRequired\"] = []string{}\n\t}\n\n\t// Parse scopesRequired if present\n\tif rawScopes, ok := r[\"scopesRequired\"]; ok {\n\t\tif scopesList, ok := rawScopes.([]any); ok {\n\t\t\tvar scopes []string\n\t\t\tfor _, s := range scopesList {\n\t\t\t\tif str, ok := s.(string); ok {\n\t\t\t\t\tscopes = append(scopes, str)\n\t\t\t\t}\n\t\t\t}\n\t\t\tr[\"scopesRequired\"] = scopes\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"scopesRequired must be a list of strings\")\n\t\t}\n\t}\n\n\t// validify parameter references\n\tif rawParams, ok := r[\"parameters\"]; ok {\n\t\tif paramsList, ok := rawParams.([]any); ok {\n\t\t\t// Turn params into a map\n\t\t\tvalidParamNames := make(map[string]bool)\n\t\t\tfor _, rawP := range paramsList {\n\t\t\t\tif pMap, ok := rawP.(map[string]any); ok {\n\t\t\t\t\tif pName, ok := pMap[\"name\"].(string); ok && pName != \"\" {\n\t\t\t\t\t\tvalidParamNames[pName] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Validate references\n\t\t\tfor i, rawP := range paramsList {","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/config.go#L467-L503","documentation":"The tool's `scopesRequired` field was present but is not a list of strings (r[\"scopesRequired\"] failed the []any assertion). The parser normalizes scope lists into []string and rejects anything else so the tool manifest can advertise required scopes correctly.","triggerScenarios":"A tools entry has `scopesRequired: my-scope` (bare string instead of list), `scopesRequired: {a: b}` (map), or `scopesRequired: [1, 2]` (non-string elements still pass the []any check but non-string items are silently dropped — the error fires only when the whole value is not a list).","commonSituations":"Writing a single scope without brackets; YAML merging producing a map; pasting comma-separated scopes as one string; indentation errors nesting scopes under the wrong key.","solutions":["Wrap the value in a YAML list: scopesRequired: [scope1, scope2]","Remove scopesRequired if the tool needs no scopes (it is optional)","Ensure every element is a plain string"],"exampleFix":"// before\n  scopesRequired: https://www.googleapis.com/auth/cloud-platform\n// after\n  scopesRequired:\n    - https://www.googleapis.com/auth/cloud-platform","handlingStrategy":"type-guard","validationCode":"func validateScopes(cfg map[string]any) error {\n  raw, ok := cfg[\"scopesRequired\"]\n  if !ok { return nil }\n  list, ok := raw.([]any)\n  if !ok { return fmt.Errorf(\"scopesRequired must be a list\") }\n  for _, s := range list {\n    if _, ok := s.(string); !ok { return fmt.Errorf(\"scopesRequired items must be strings\") }\n  }\n  return nil\n}","typeGuard":"func isStringList(v any) bool {\n  list, ok := v.([]any)\n  if !ok { return false }\n  for _, s := range list { if _, ok := s.(string); !ok { return false } }\n  return true\n}","tryCatchPattern":null,"preventionTips":["Always write scopesRequired as a YAML list, even for one scope","Never write a bare string or map for scopesRequired","Validate with a YAML schema before deploy"],"tags":["config","yaml","scopes","validation"],"backgroundTag":"schema-validation-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"}