{"record":{"id":"f86ab7f5ef645c28","repo":"github/github-mcp-server","slug":"response-did-not-include-the-deleted-project-view","errorCode":null,"errorMessage":"response did not include the deleted project view","messagePattern":"response did not include the deleted project view","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/projects.go","lineNumber":2300,"sourceCode":"\t\treturn utils.NewToolResultError(fmt.Sprintf(\"%s: response did not include a project view\", ProjectViewUpdateFailedError)), nil, nil\n\t}\n\treturn MarshalledTextResult(convertToMinimalProjectView(mutation.UpdateProjectV2View.ProjectV2View)), nil, nil\n}\n\nfunc deleteProjectViewByID(ctx context.Context, gqlClient *githubv4.Client, viewID githubv4.ID) error {\n\tinput := DeleteProjectV2ViewInput{ViewID: viewID}\n\tvar mutation struct {\n\t\tDeleteProjectV2View struct {\n\t\t\tProjectV2View struct {\n\t\t\t\tID githubv4.ID\n\t\t\t} `graphql:\"projectV2View\"`\n\t\t} `graphql:\"deleteProjectV2View(input: $input)\"`\n\t}\n\tif err := gqlClient.Mutate(ctx, &mutation, input, nil); err != nil {\n\t\treturn err\n\t}\n\tif id := mutation.DeleteProjectV2View.ProjectV2View.ID; id == nil || id == \"\" {\n\t\treturn errors.New(\"response did not include the deleted project view\")\n\t}\n\treturn nil\n}\n\nfunc deleteProjectView(ctx context.Context, gqlClient *githubv4.Client, args map[string]any, owner, ownerType string, projectNumber int) (*mcp.CallToolResult, any, error) {\n\tviewID, err := RequiredParam[string](args, \"view_id\")\n\tif err != nil {\n\t\treturn utils.NewToolResultError(err.Error()), nil, nil\n\t}\n\tif _, err := verifyProjectViewParent(ctx, gqlClient, viewID, owner, ownerType, projectNumber); err != nil {\n\t\treturn utils.NewToolResultError(fmt.Sprintf(\"%s: %v\", ProjectViewDeleteFailedError, err)), nil, nil\n\t}\n\tif err := deleteProjectViewByID(ctx, gqlClient, githubv4.ID(viewID)); err != nil {\n\t\treturn utils.NewToolResultError(fmt.Sprintf(\"%s: %v\", ProjectViewDeleteFailedError, err)), nil, nil\n\t}\n\treturn MarshalledTextResult(map[string]string{\"deleted_view_id\": viewID}), nil, nil\n}\n","sourceCodeStart":2282,"sourceCodeEnd":2318,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/projects.go#L2282-L2318","documentation":"Fourth guard of validateBlamePath for get_file_blame: any rune below 0x20 (space is 0x20 and allowed) or equal to 0x7f (DEL) is rejected. Control characters would corrupt the GraphQL variable or match nothing in the git tree, so the server fails fast with 'path must not contain control characters'. Note the check iterates runes, so valid UTF-8 multibyte characters pass.","triggerScenarios":"Paths containing '\\t', '\\n', '\\r', or DEL - typically from copy-paste with a trailing newline, string building with embedded escapes, or terminal input that captures control keystrokes.","commonSituations":"Piping paths from shell commands that append newlines; splitting file lists on the wrong delimiter; LLM-generated arguments with literal escape sequences; editors inserting BOM-like characters (0x00-0x1f range).","solutions":["Trim whitespace and control runes from the path before sending","When paths come from files or pipes, strip the trailing newline explicitly","Add a client-side scan for bytes < 0x20 and 0x7f before the tool call"],"exampleFix":"// before: trailing newline from a shell pipeline\n{\"path\":\"src/main.go\\n\"}\n\n// after\n{\"path\":\"src/main.go\"}","handlingStrategy":"validation","validationCode":"func hasControlRunes(p string) bool {\n\tfor _, r := range p {\n\t\tif r < 0x20 || r == 0x7f {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","typeGuard":"func isBlamePathError(err error) bool {\n\treturn err != nil && strings.HasPrefix(err.Error(), \"path must\")\n}","tryCatchPattern":"path = strings.TrimFunc(path, func(r rune) bool { return r < 0x20 || r == 0x7f })\nif hasControlRunes(path) {\n\treturn nil, fmt.Errorf(\"path contains control characters\")\n}\nres, _, err := callGetFileBlame(ctx, buildArgs(owner, repo, path))","preventionTips":["Strip trailing newlines when paths come from shells, files, or pipes","Scan for bytes < 0x20 and 0x7f before sending","Avoid building paths with fmt escapes interpolated from user input","UTF-8 above 0x20 is fine - only control and DEL runes are rejected"],"tags":["go","validation","user-input","blame"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}