{"record":{"id":"dfbfde46ee558104","repo":"github/github-mcp-server","slug":"issue-fields-must-be-an-array","errorCode":null,"errorMessage":"issue_fields must be an array","messagePattern":"issue_fields must be an array","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/issues.go","lineNumber":253,"sourceCode":"\tissueFieldsRaw, exists := args[\"issue_fields\"]\n\tif !exists {\n\t\treturn nil, nil\n\t}\n\n\tvar inputMaps []map[string]any\n\tswitch v := issueFieldsRaw.(type) {\n\tcase []any:\n\t\tfor _, item := range v {\n\t\t\titemMap, ok := item.(map[string]any)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"each issue_fields item must be an object\")\n\t\t\t}\n\t\t\tinputMaps = append(inputMaps, itemMap)\n\t\t}\n\tcase []map[string]any:\n\t\tinputMaps = v\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"issue_fields must be an array\")\n\t}\n\n\tissueFields := make([]issueWriteFieldInput, 0, len(inputMaps))\n\tfor _, itemMap := range inputMaps {\n\t\tfieldName, err := RequiredParam[string](itemMap, \"field_name\")\n\t\tif err != nil || strings.TrimSpace(fieldName) == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"field_name is required for each issue_fields item\")\n\t\t}\n\n\t\tfieldOptionName, err := OptionalParam[string](itemMap, \"field_option_name\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tdeleteField, _ := OptionalParam[bool](itemMap, \"delete\")\n\t\tvalue, hasValue := itemMap[\"value\"]\n\t\tif hasValue && value == nil {\n\t\t\treturn nil, fmt.Errorf(\"value cannot be null for field %q\", fieldName)","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/issues.go#L235-L271","documentation":"optionalIssueWriteFields (pkg/github/issues.go:253) type-switches the issue_fields argument. This error fires when issue_fields is present but is neither []any nor []map[string]any — i.e. the JSON value is a scalar, a single object, or null-shaped non-array. The field must be omitted entirely when unused, or an array of field-update objects.","triggerScenarios":"update_issue with issue_fields=\"Priority\" (string), issue_fields={\"field_name\":\"Priority\"} (single object), or issue_fields=42. The type switch falls through to default and rejects the shape.","commonSituations":"Tool callers collapsing the array when updating a single field; LLMs emitting one object instead of a one-element array; config pipelines injecting strings.","solutions":["Wrap the value in an array: issue_fields=[{\"field_name\":\"Priority\",...}]","Omit issue_fields entirely when not updating fields","Validate the arg shape client-side against the tool schema before sending"],"exampleFix":"# before\n{\"issue_fields\": {\"field_name\": \"Priority\", \"value\": \"P0\"}}\n\n# after\n{\"issue_fields\": [{\"field_name\": \"Priority\", \"field_option_name\": \"P0\"}]}","handlingStrategy":"validation","validationCode":"if raw, ok := args[\"issue_fields\"]; ok {\n    switch raw.(type) {\n    case []any, []map[string]any:\n        // ok\n    default:\n        return errors.New(\"issue_fields must be an array of objects\")\n    }\n}","typeGuard":"func isIssueFieldsArray(v any) bool {\n    switch v.(type) {\n    case []any, []map[string]any, nil:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Omit issue_fields when not setting fields; an absent key is the clean no-op","Wrap single-field updates in a one-element array rather than passing a bare object","Keep an integration test that round-trips every tool payload you generate"],"tags":["go","validation","issue-fields","mcp"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}