{"record":{"id":"10253ae3bd292e0d","repo":"github/github-mcp-server","slug":"s-must-be-a-non-empty-string","errorCode":null,"errorMessage":"%s must be a non-empty string","messagePattern":"(.+?) must be a non-empty string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/projects_batch.go","lineNumber":464,"sourceCode":"\tfor _, key := range []string{\"node_id\", \"item_id\", \"item_owner\", \"item_repo\", \"issue_number\"} {\n\t\tif v, ok := entry[key]; ok {\n\t\t\tref[key] = v\n\t\t}\n\t}\n\tif len(ref) == 0 {\n\t\treturn nil\n\t}\n\treturn ref\n}\n\nfunc stringFromEntry(entry map[string]any, key string) (string, error) {\n\tv, ok := entry[key]\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"missing %s\", key)\n\t}\n\ts, ok := v.(string)\n\tif !ok || s == \"\" {\n\t\treturn \"\", fmt.Errorf(\"%s must be a non-empty string\", key)\n\t}\n\treturn s, nil\n}\n\nfunc intFromEntry(entry map[string]any, key string) (int, error) {\n\tv, ok := entry[key]\n\tif !ok {\n\t\treturn 0, fmt.Errorf(\"missing %s\", key)\n\t}\n\tn, err := validatePositiveInt64(v)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"%s must be a positive integer: %w\", key, err)\n\t}\n\tif n > math.MaxInt32 {\n\t\treturn 0, fmt.Errorf(\"%s exceeds the GraphQL Int maximum of %d\", key, int64(math.MaxInt32))\n\t}\n\treturn int(n), nil\n}","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/projects_batch.go#L446-L482","documentation":"Raised by stringFromEntry (pkg/github/projects_batch.go:464) when item_owner or item_repo exists but its value is not a non-empty string — i.e. it is null, a number, a bool, an array, or \"\". It is wrapped into the 'must all be provided together' message by parseItemRef and the item is rejected before any API call.","triggerScenarios":"{\"item_owner\": null, \"item_repo\":\"repo\", \"issue_number\":7}, {\"item_owner\": \"\"} from a blank template expansion, or {\"item_repo\": 12345} when a numeric org/repo field is forwarded unconverted.","commonSituations":"Upstream serializers that emit explicit nulls for missing columns; templating that renders empty strings; owner/repo stored as numeric codes in an internal DB and passed through without mapping to the slug.","solutions":["Ensure item_owner and item_repo are non-empty strings (GitHub slugs, e.g. \"octocat\" and \"hello-world\")","Filter or fix rows whose owner/repo is null or empty before building the batch","Convert non-string sources to strings explicitly at the boundary","Note null is not treated as missing — remove the key entirely if you want the 'missing' path, but either way the item needs a real value"],"exampleFix":"// before\n{\"item_owner\": null, \"item_repo\": \"repo\", \"issue_number\": 7}\n// after\n{\"item_owner\": \"octocat\", \"item_repo\": \"repo\", \"issue_number\": 7}","handlingStrategy":"validation","validationCode":"for _, k := range []string{\"item_owner\", \"item_repo\"} {\n\ts, ok := entry[k].(string)\n\tif !ok || s == \"\" {\n\t\treturn fmt.Errorf(\"%s must be a non-empty string\", k)\n\t}\n}","typeGuard":"func isNonEmptyString(v any) bool { s, ok := v.(string); return ok && s != \"\" }","tryCatchPattern":null,"preventionTips":["Blank-check owner/repo columns at ingestion and drop invalid rows","Map internal numeric codes to real GitHub slugs before building items","Null and empty string are both rejected — serialize omitted values as absent keys only if the whole item will be skipped"],"tags":["github-projects","batch","input-validation","type-mismatch","issue-ref"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}