{"record":{"id":"6958645e5f91aa70","repo":"github/github-mcp-server","slug":"bad-request","errorCode":null,"errorMessage":"bad request","messagePattern":"bad request","errorType":"error_code","errorClass":"ErrBadRequest","httpStatus":400,"severity":"error","filePath":"pkg/http/mark/mark.go","lineNumber":23,"sourceCode":"\n// This list of errors is not exhaustive, but is a good starting point for most\n// applications. Feel free to add more as needed, but don't go overboard.\n// Remember, the specific types of errors are only important so far as someone\n// calling your code might want to write logic to handle each type of error\n// differently.\n//\n// Do not add application-specific errors to this list. Instead, just define\n// your own package with your own application-specific errors, and use this\n// package to mark errors with them. The errors in this package are not special,\n// they're just plain old errors.\n//\n// Not all errors need to be marked. An error that is not marked should be\n// treated as an unexpected error that cannot be handled by calling code. This\n// is often the case for network errors or logic errors.\nvar (\n\tErrNotFound        = errors.New(\"not found\")\n\tErrAlreadyExists   = errors.New(\"already exists\")\n\tErrBadRequest      = errors.New(\"bad request\")\n\tErrUnauthorized    = errors.New(\"unauthorized\")\n\tErrCancelled       = errors.New(\"request cancelled\")\n\tErrUnavailable     = errors.New(\"unavailable\")\n\tErrTimedout        = errors.New(\"request timed out\")\n\tErrTooLarge        = errors.New(\"request is too large\")\n\tErrTooManyRequests = errors.New(\"too many requests\")\n\tErrForbidden       = errors.New(\"forbidden\")\n)\n\n// With wraps err with another error that will return true from errors.Is and\n// errors.As for both err and markErr, and anything either may wrap.\nfunc With(err, markErr error) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\treturn marked{wrapped: err, mark: markErr}\n}\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/http/mark/mark.go#L5-L41","documentation":"ErrBadRequest is a generic 'mark' sentinel in pkg/http/mark used to classify client-side request errors. The mark package itself never throws it on its own; concrete errors wrap it via mark.With or fmt.Errorf('%w: ...'), and calling code detects it with errors.Is. In this codebase the primary producers are pkg/utils/token.go's Authorization header errors: missing header, badly formatted header, or unsupported scheme/token.","triggerScenarios":"Calling the remote/HTTP server endpoints without an Authorization header (ErrMissingAuthorizationHeader); sending a token GitHub does not recognize (no ghp_/github_pat_/gho_/ghu_/ghs_ prefix and not a legacy 40-char hex token) yielding ErrBadAuthorizationHeader; sending a 'GitHub-Bearer ...' header, which is explicitly rejected as ErrUnsupportedAuthorizationHeader.","commonSituations":"Using the remote GitHub MCP server behind a proxy that strips Authorization headers; passing an opaque proxy token or JWT where a GitHub token is required; legacy deployments sending dotcom encrypted tokens; clients omitting the 'Bearer ' prefix in ways that alter the parsed token value.","solutions":["Send a valid GitHub token: 'Authorization: Bearer ghp_...' (classic PAT), github_pat_... (fine-grained), gho_/ghu_/ghs_ (OAuth/App tokens)","If a proxy fronts the server, ensure it forwards the Authorization header unmodified","If you must accept non-GitHub tokens, wrap the server with your own auth layer rather than relying on ParseAuthorizationHeader","On the server side, map errors.Is(err, mark.ErrBadRequest) to an HTTP 400 response with the wrapped detail"],"exampleFix":"// client: before\nreq.Header.Set(\"Authorization\", token) // raw token or wrong scheme\n\n// client: after\nreq.Header.Set(\"Authorization\", \"Bearer \"+githubToken) // ghp_..., github_pat_..., gho_..., ghu_..., ghs_...","handlingStrategy":"validation","validationCode":"// Client-side: build a correctly formed header before sending\nvalidPrefixes := []string{\"ghp_\", \"github_pat_\", \"gho_\", \"ghu_\", \"ghs_\"}\nisGitHubToken := func(tok string) bool {\n    for _, p := range validPrefixes {\n        if strings.HasPrefix(tok, p) {\n            return true\n        }\n    }\n    return regexp.MustCompile(`^[a-f0-9]{40}$`).MatchString(tok) // legacy PAT\n}\nif !isGitHubToken(token) {\n    return errors.New(\"token is not a GitHub token; get one at github.com/settings/tokens\")\n}\nreq.Header.Set(\"Authorization\", \"Bearer \"+token)","typeGuard":"// errors.Is narrows any wrapped cause back to the bad-request mark\nfunc isBadRequest(err error) bool {\n    return err != nil && errors.Is(err, mark.ErrBadRequest)\n}","tryCatchPattern":"// Server-side: map the mark to HTTP 400 with the wrapped detail\nif err := utils.ParseAuthorizationHeader(req); err != nil {\n    if errors.Is(err, mark.ErrBadRequest) {\n        http.Error(w, err.Error(), http.StatusBadRequest)\n        return\n    }\n    http.Error(w, \"internal error\", http.StatusInternalServerError)\n}","preventionTips":["Always send 'Authorization: Bearer <github-token>' with one of the ghp_/github_pat_/gho_/ghu_/ghs_ prefixes","Never send 'GitHub-Bearer' headers — explicitly unsupported","Verify proxies forward Authorization headers unmodified","Check errors.Is(err, mark.ErrBadRequest) to distinguish client errors from server failures"],"tags":["http","authentication","authorization-header","token","sentinel-error"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}