{"record":{"id":"190038ef4c4f7e19","repo":"ory/hydra","slug":"invalid-action","errorCode":null,"errorMessage":"Invalid action","messagePattern":"Invalid action","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"cmd/cmd_perform_authorization_code.go","lineNumber":445,"sourceCode":"\t\t\t}).Execute()\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tdefer res.Body.Close() //nolint:errcheck\n\t\thttp.Redirect(w, r, req.RedirectTo, http.StatusFound)\n\n\tcase \"deny\":\n\t\treq, res, err := rt.cl.OAuth2API.RejectOAuth2LoginRequest(r.Context()).LoginChallenge(r.FormValue(\"ls\")).Execute()\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tdefer res.Body.Close() //nolint:errcheck\n\t\thttp.Redirect(w, r, req.RedirectTo, http.StatusFound)\n\n\tdefault:\n\t\thttp.Error(w, \"Invalid action\", http.StatusBadRequest)\n\t}\n}\n\nfunc (rt *router) consentGET(w http.ResponseWriter, r *http.Request) {\n\treq, raw, err := rt.cl.OAuth2API.GetOAuth2ConsentRequest(r.Context()).\n\t\tConsentChallenge(r.URL.Query().Get(\"consent_challenge\")).\n\t\tExecute()\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer raw.Body.Close() //nolint:errcheck\n\n\tif rt.skip && req.GetSkip() {\n\t\treq, res, err := rt.cl.OAuth2API.AcceptOAuth2ConsentRequest(r.Context()).\n\t\t\tConsentChallenge(req.Challenge).\n\t\t\tAcceptOAuth2ConsentRequest(openapi.AcceptOAuth2ConsentRequest{\n\t\t\t\tGrantScope:               req.GetRequestedScope(),","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/cmd/cmd_perform_authorization_code.go#L427-L463","documentation":"A handler-generated error: loginPOST received an \"action\" form value that is neither \"accept\" nor \"deny\", so the switch's default case rejects the request with 400 \"Invalid action\". This is local input validation in the example app, not a Hydra error.","triggerScenarios":"Posting to /login without an action field, with a misspelled action (e.g. \"Accept\"), or via curl/automation that omits the button value the HTML form normally supplies.","commonSituations":"Custom clients or scripts hitting the login endpoint directly without the action field; HTML form button name/value changed or removed in a template edit; proxies stripping form fields.","solutions":["Include action=accept or action=deny in the POSTed form","Check the login template still renders the submit buttons with name=\"action\"","Handle unknown actions gracefully by redirecting to a fresh flow instead of a bare 400","Case-normalize the action value before the switch"],"exampleFix":"// before\ndefault:\n\thttp.Error(w, \"Invalid action\", http.StatusBadRequest)\n// after\ndefault:\n\tlog.Printf(\"login: unknown action %q\", r.FormValue(\"action\"))\n\thttp.Error(w, \"invalid action; must be accept or deny\", http.StatusBadRequest)","handlingStrategy":"validation","validationCode":"func knownLoginAction(a string) bool {\n\tswitch a {\n\tcase \"accept\", \"deny\":\n\t\treturn true\n\t}\n\treturn false\n}\n// before the switch:\nif !knownLoginAction(r.FormValue(\"action\")) {\n\thttp.Error(w, \"invalid action; must be accept or deny\", http.StatusBadRequest)\n\treturn\n}","typeGuard":"func isLoginAction(s string) bool {\n\treturn s == \"accept\" || s == \"deny\"\n}","tryCatchPattern":null,"preventionTips":["Keep the action value a single canonical string in forms and scripts","Use buttons with name=\"action\" and fixed value attributes","Case-normalize input before dispatch","Reject unknown actions early with a clear message"],"tags":["http","validation","hydra"],"backgroundTag":"invalid-request-action","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}