{"record":{"id":"c9d99d01fea0e05f","repo":"onetimesecret/onetimesecret","slug":"too-many-password-reset-requests-please-try-again","errorCode":null,"errorMessage":"Too many password reset requests. Please try again later.","messagePattern":"Too many password reset requests\\. Please try again later\\.","errorType":"exception","errorClass":"Onetime::LimitExceeded","httpStatus":429,"severity":"error","filePath":"lib/onetime/security/reset_request_rate_limiter.rb","lineNumber":290,"sourceCode":"      end\n\n      private\n\n      # Atomically check-and-record one tier via CHECK_AND_RECORD_SCRIPT.\n      # Raises LimitExceeded when the tier is locked; otherwise logs as the\n      # count approaches/reaches the cap (the detection tie-in for #3872 —\n      # alert on these alongside the reset_password_request_no_account events).\n      # The cap-hit also writes one ColonelAuditEvent, so the signal is queryable\n      # and not only greppable — see record_reset_request_throttle_audit.\n      def enforce_reset_request_tier!(keys, max_attempts, tier_label, subject)\n        allowed, detail = reset_request_redis.eval(\n          CHECK_AND_RECORD_SCRIPT,\n          keys: [keys[:attempts], keys[:lockout]],\n          argv: [reset_request_window, max_attempts, reset_request_lockout],\n        )\n\n        if allowed.to_i != 1\n          raise Onetime::LimitExceeded.new(\n            'Too many password reset requests. Please try again later.',\n            retry_after: detail.to_i.positive? ? detail.to_i : reset_request_lockout,\n            max_attempts: max_attempts,\n          )\n        end\n\n        count = detail.to_i\n        if count >= max_attempts\n          # This cap-reaching request was itself ALLOWED (the Lua script locks\n          # after incrementing); the lockout applies to subsequent requests.\n          obscured = obscured_reset_request_subject(tier_label, subject)\n          OT.le \"[ResetRequestRateLimiter] #{tier_label} #{obscured} \" \\\n                \"hit cap (#{count}/#{max_attempts}); locked for #{reset_request_lockout}s\" \\\n                \"#{collapsed_ip_tier_hint(tier_label)}\"\n          record_reset_request_throttle_audit(tier_label, obscured, count, max_attempts)\n        elsif count >= max_attempts - 1\n          OT.li \"[ResetRequestRateLimiter] #{tier_label} #{obscured_reset_request_subject(tier_label, subject)} at #{count}/#{max_attempts} requests\"\n        end","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/onetimesecret/onetimesecret/blob/f81295e41bc3e808a3dd2cbea03ef65401a662e4/lib/onetime/security/reset_request_rate_limiter.rb#L272-L308","documentation":"Error \"Too many password reset requests. Please try again later.\" thrown in onetimesecret/onetimesecret.","triggerScenarios":"Thrown at lib/onetime/security/reset_request_rate_limiter.rb:290 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Wait for the rate-limit window to pass; check the mailbox (including spam) for the earlier reset email before requesting another."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f81295e41bc3e808a3dd2cbea03ef65401a662e4","analyzedAt":"2026-08-23T21:13:10.635Z","schemaVersion":2},"datasetVersion":"2026-08-24T02:17:37.098Z"}