{"record":{"id":"e0bf7cc57c14b911","repo":"github/github-mcp-server","slug":"field-q-is-text-value-must-be-a-string","errorCode":null,"errorMessage":"field %q is TEXT; value must be a string","messagePattern":"field %q is TEXT; value must be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/projects_batch.go","lineNumber":580,"sourceCode":"\tcandidates := make([]any, 0, len(fields))\n\tfor _, field := range fields {\n\t\tcandidates = append(candidates, map[string]any{\n\t\t\t\"id\":        field.ID,\n\t\t\t\"name\":      field.Name,\n\t\t\t\"data_type\": field.DataType,\n\t\t})\n\t}\n\treturn candidates\n}\n\nfunc convertProjectFieldValue(field *ResolvedField, raw any) (githubv4.ProjectV2FieldValue, error) {\n\tvar zero githubv4.ProjectV2FieldValue\n\n\tswitch field.DataType {\n\tcase \"TEXT\":\n\t\ts, ok := raw.(string)\n\t\tif !ok {\n\t\t\treturn zero, fmt.Errorf(\"field %q is TEXT; value must be a string\", field.Name)\n\t\t}\n\t\tv := githubv4.String(s)\n\t\treturn githubv4.ProjectV2FieldValue{Text: &v}, nil\n\n\tcase \"NUMBER\":\n\t\tf, ok := toFloat64(raw)\n\t\tif !ok {\n\t\t\treturn zero, fmt.Errorf(\"field %q is NUMBER; value must be a number\", field.Name)\n\t\t}\n\t\tv := githubv4.Float(f)\n\t\treturn githubv4.ProjectV2FieldValue{Number: &v}, nil\n\n\tcase \"DATE\":\n\t\ts, ok := raw.(string)\n\t\tif !ok {\n\t\t\treturn zero, fmt.Errorf(\"field %q is DATE; value must be a YYYY-MM-DD string\", field.Name)\n\t\t}\n\t\tt, err := time.Parse(\"2006-01-02\", s)","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/projects_batch.go#L562-L598","documentation":"Raised by convertProjectFieldValue (pkg/github/projects_batch.go:580) after the target field was resolved and found to have DataType \"TEXT\", but the supplied value is not a Go string (number, bool, array, object, or null). The library only wraps values into ProjectV2FieldValue.Text for strings. When this fires during pre-flight conversion the whole batch fails before any write; per-item occurrences surface as item errors.","triggerScenarios":"A Project V2 text field (e.g. \"Notes\", \"Status\" text field) updated with \"value\": 123, true, null, or [\"a\",\"b\"]. The field's data type comes from GitHub, so the mismatch is purely on the caller's side.","commonSituations":"Numeric-looking text (ticket numbers, sizes) sent unquoted from JSON numbers; booleans for flags; a schema-less client forwarding whatever type the source column had; null intended to clear a field (this tool does not clear — that is a different operation).","solutions":["Send the value as a string: \"value\": \"123\" instead of 123","If you meant to clear the field, use the clear operation/update_project_item, not a null value here","Check the field's data type first (list_project_fields) and shape values to match","For values from dynamic sources, stringify numbers/booleans before building the payload"],"exampleFix":"// before (field \"Size\" is TEXT)\n{\"updated_field\": {\"name\": \"Size\", \"value\": 42}}\n// after\n{\"updated_field\": {\"name\": \"Size\", \"value\": \"42\"}}","handlingStrategy":"type-guard","validationCode":"// After resolving field metadata, gate the value on DataType\nswitch field.DataType {\ncase \"TEXT\":\n\tif _, ok := value.(string); !ok {\n\t\treturn fmt.Errorf(\"field %s is TEXT: stringify the value\", field.Name)\n\t}\n}","typeGuard":"func matchesFieldType(dataType string, v any) bool {\n\tswitch dataType {\n\tcase \"TEXT\", \"DATE\", \"SINGLE_SELECT\", \"ITERATION\":\n\t\ts, ok := v.(string); return ok && s != \"\"\n\tcase \"NUMBER\":\n\t\tswitch v.(type) {\n\t\tcase float64, int, int64: return true\n\t\t}\n\t\treturn false\n\t}\n\treturn false\n}","tryCatchPattern":null,"preventionTips":["Fetch the field's data_type once per run and coerce values to it before batching","Stringify numeric-looking text (\"42\") and never send bools to text fields","To clear a field, use the clear operation — null values are not the clear path here"],"tags":["github-projects","batch","input-validation","type-mismatch","field-value"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}