{"record":{"id":"52a50ca5fefe36eb","repo":"github/github-mcp-server","slug":"updated-field-must-set-either-id-or-name-not-both-52a50c","errorCode":null,"errorMessage":"updated_field must set either id or name, not both","messagePattern":"updated_field must set either id or name, not both","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/projects_batch.go","lineNumber":518,"sourceCode":"\nfunc parseBatchFieldSpec(raw any) (batchFieldSpec, error) {\n\tvar spec batchFieldSpec\n\tinput, ok := raw.(map[string]any)\n\tif !ok || input == nil {\n\t\treturn spec, fmt.Errorf(\"updated_field must be an object\")\n\t}\n\n\tvalue, hasValue := input[\"value\"]\n\tif !hasValue {\n\t\treturn spec, fmt.Errorf(\"updated_field.value is required\")\n\t}\n\tspec.value = value\n\n\tidField, hasID := input[\"id\"]\n\tnameField, hasName := input[\"name\"]\n\tswitch {\n\tcase hasID && hasName:\n\t\treturn spec, fmt.Errorf(\"updated_field must set either id or name, not both\")\n\tcase !hasID && !hasName:\n\t\treturn spec, fmt.Errorf(\"updated_field requires either id or name\")\n\tcase hasID:\n\t\tid, err := validatePositiveInt64(idField)\n\t\tif err != nil {\n\t\t\treturn spec, fmt.Errorf(\"updated_field.id: %w\", err)\n\t\t}\n\t\tspec.id = id\n\tdefault:\n\t\tname, ok := nameField.(string)\n\t\tif !ok || name == \"\" {\n\t\t\treturn spec, fmt.Errorf(\"updated_field.name must be a non-empty string\")\n\t\t}\n\t\tspec.name = name\n\t}\n\treturn spec, nil\n}\n","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/projects_batch.go#L500-L536","documentation":"Raised by parseBatchFieldSpec (pkg/github/projects_batch.go:518) when the updated_field object sets both 'id' and 'name'. The library refuses ambiguity about which field identifier wins and fails the whole request before any item is processed — this is a top-level argument error, not a per-item one.","triggerScenarios":"{\"updated_field\": {\"id\": 123456, \"name\": \"Status\", \"value\": \"Done\"}} — both identifier keys present. Both keys are looked up with Go's two-value map access, so \"id\": null plus \"name\": \"Status\" still counts as both set.","commonSituations":"Merging a cached field record (has id) with a human-readable override (has name); serializers that emit null for unset keys, which still counts as present here; defensive clients that include every known property.","solutions":["Delete one of the two keys — keep name for readability or id to skip the field-by-name resolution","If your source has both, pick id when it came from a recent list_project_fields call","Strip null-valued keys before sending; null counts as present for this check","Remember the choice applies to the entire batch, not one item"],"exampleFix":"// before\n{\"updated_field\": {\"id\": 123456, \"name\": \"Status\", \"value\": \"Done\"}}\n// after\n{\"updated_field\": {\"name\": \"Status\", \"value\": \"Done\"}}","handlingStrategy":"validation","validationCode":"_, hasID := spec[\"id\"]\n_, hasName := spec[\"name\"]\nif hasID && hasName {\n\treturn fmt.Errorf(\"updated_field: set only one of id or name\")\n}","typeGuard":"func hasExactlyOneFieldID(spec map[string]any) bool {\n\t_, id := spec[\"id\"]\n\t_, name := spec[\"name\"]\n\treturn id != name // exactly one true\n}","tryCatchPattern":null,"preventionTips":["Strip null-valued keys before sending — null counts as present for this check","Choose name for readability, id only when freshly fetched from list_project_fields","Keep one source of truth for the field identifier in your config"],"tags":["github-projects","batch","input-validation","conflicting-input","updated-field"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}