{"record":{"id":"b05cc31c2c677fa6","repo":"github/github-mcp-server","slug":"repo-is-required","errorCode":null,"errorMessage":"repo is required","messagePattern":"repo is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/github/repository_resource.go","lineNumber":130,"sourceCode":"func RepositoryResourceContentsHandler(resourceURITemplate *uritemplate.Template) mcp.ResourceHandler {\n\treturn func(ctx context.Context, request *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {\n\t\tdeps := MustDepsFromContext(ctx)\n\t\t// Match the URI to extract parameters\n\t\turiValues := resourceURITemplate.Match(request.Params.URI)\n\t\tif uriValues == nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to match URI: %s\", request.Params.URI)\n\t\t}\n\n\t\t// Extract required vars\n\t\towner := uriValues.Get(\"owner\").String()\n\t\trepo := uriValues.Get(\"repo\").String()\n\n\t\tif owner == \"\" {\n\t\t\treturn nil, errors.New(\"owner is required\")\n\t\t}\n\n\t\tif repo == \"\" {\n\t\t\treturn nil, errors.New(\"repo is required\")\n\t\t}\n\n\t\tpathValue := uriValues.Get(\"path\")\n\t\tpathComponents := pathValue.List()\n\t\tvar path string\n\n\t\tif len(pathComponents) == 0 {\n\t\t\tpath = pathValue.String()\n\t\t} else {\n\t\t\tpath = strings.Join(pathComponents, \"/\")\n\t\t}\n\n\t\topts := &github.RepositoryContentGetOptions{}\n\t\trawOpts := &raw.ContentOpts{}\n\n\t\tsha := uriValues.Get(\"sha\").String()\n\t\tif sha != \"\" {\n\t\t\topts.Ref = sha","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/repository_resource.go#L112-L148","documentation":"Raised when json.Marshal fails on the get_file_blame result struct (Ranges, Commits, PageInfo, TotalRanges, Truncated - with Ranges already nil-guarded to []BlameRange{}). All fields are JSON-safe slices/structs of strings and ints, so Go's encoder would need a NaN/Inf, chan, func, or cyclic value to fail. This is a defensive invariant that is effectively unreachable with stock types.","triggerScenarios":"Only possible if a fork adds an unmarshalable field to BlameRange/BlameCommit/pageInfo types, or a race corrupts the result struct between assembly and marshal. Values built from decoded GraphQL responses never trigger it.","commonSituations":"Forked DTOs with unsupported field types; version skew between github-mcp-server forks; local patches to the blame payload.","solutions":["Treat as a bug: capture the tool input (owner/repo/path/ref) and report upstream","Upgrade to a released github-mcp-server build","If maintaining a fork, keep blame payload fields JSON-safe (strings, ints, bools, slices)"],"exampleFix":"// before: fork adds an unsupported field\ntype BlameCommit struct {\n\t// ...\n\tFetch chan struct{} `json:\"fetch\"` // marshal fails\n}\n\n// after\ntype BlameCommit struct {\n\t// ...\n\tFetched bool `json:\"fetched\"`\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isMarshalError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to marshal\")\n}","tryCatchPattern":"result, _, err := callGetFileBlame(ctx, args)\nif err != nil && isMarshalError(err) {\n\t// internal serialization bug: capture inputs and report upstream; not retryable\n\tlog.Printf(\"blame marshal bug: args=%v err=%v\", args, err)\n\treturn err\n}","preventionTips":["Run released github-mcp-server builds; keep blame DTOs unmodified","If forking, keep BlameRange/BlameCommit fields to strings and ints","Add a CI test that round-trip marshals the blame payload"],"tags":["go","json","serialization","defensive"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}