github/github-mcp-server · error

field %q is TEXT; value must be a string

Error message

field %q is TEXT; value must be a string

What it means

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.

Source

Thrown at pkg/github/projects_batch.go:580

	candidates := make([]any, 0, len(fields))
	for _, field := range fields {
		candidates = append(candidates, map[string]any{
			"id":        field.ID,
			"name":      field.Name,
			"data_type": field.DataType,
		})
	}
	return candidates
}

func convertProjectFieldValue(field *ResolvedField, raw any) (githubv4.ProjectV2FieldValue, error) {
	var zero githubv4.ProjectV2FieldValue

	switch field.DataType {
	case "TEXT":
		s, ok := raw.(string)
		if !ok {
			return zero, fmt.Errorf("field %q is TEXT; value must be a string", field.Name)
		}
		v := githubv4.String(s)
		return githubv4.ProjectV2FieldValue{Text: &v}, nil

	case "NUMBER":
		f, ok := toFloat64(raw)
		if !ok {
			return zero, fmt.Errorf("field %q is NUMBER; value must be a number", field.Name)
		}
		v := githubv4.Float(f)
		return githubv4.ProjectV2FieldValue{Number: &v}, nil

	case "DATE":
		s, ok := raw.(string)
		if !ok {
			return zero, fmt.Errorf("field %q is DATE; value must be a YYYY-MM-DD string", field.Name)
		}
		t, err := time.Parse("2006-01-02", s)

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Send the value as a string: "value": "123" instead of 123
  2. If you meant to clear the field, use the clear operation/update_project_item, not a null value here
  3. Check the field's data type first (list_project_fields) and shape values to match
  4. For values from dynamic sources, stringify numbers/booleans before building the payload

Example fix

// before (field "Size" is TEXT)
{"updated_field": {"name": "Size", "value": 42}}
// after
{"updated_field": {"name": "Size", "value": "42"}}
Defensive patterns

Strategy: type-guard

Validate before calling

// After resolving field metadata, gate the value on DataType
switch field.DataType {
case "TEXT":
	if _, ok := value.(string); !ok {
		return fmt.Errorf("field %s is TEXT: stringify the value", field.Name)
	}
}

Type guard

func matchesFieldType(dataType string, v any) bool {
	switch dataType {
	case "TEXT", "DATE", "SINGLE_SELECT", "ITERATION":
		s, ok := v.(string); return ok && s != ""
	case "NUMBER":
		switch v.(type) {
		case float64, int, int64: return true
		}
		return false
	}
	return false
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/e0bf7cc57c14b911. Report an issue: GitHub.