diff --git a/autogpt_platform/frontend/src/app/(platform)/reset-password/page.tsx b/autogpt_platform/frontend/src/app/(platform)/reset-password/page.tsx
index c1a9fe5c59..1aa69c9b24 100644
--- a/autogpt_platform/frontend/src/app/(platform)/reset-password/page.tsx
+++ b/autogpt_platform/frontend/src/app/(platform)/reset-password/page.tsx
@@ -32,12 +32,14 @@ function ResetPasswordContent() {
if (error || errorCode) {
// Check if this is an expired/used link error
+ const descLower = errorDescription?.toLowerCase() || "";
const isExpiredOrUsed =
error === "link_expired" ||
errorCode === "otp_expired" ||
- error === "access_denied" ||
- errorDescription?.toLowerCase().includes("expired") ||
- errorDescription?.toLowerCase().includes("invalid");
+ descLower.includes("expired") ||
+ descLower.includes("invalid") ||
+ // access_denied alone is too broad - only treat as expired when combined with otp indicators
+ (error === "access_denied" && errorCode === "otp_expired");
if (isExpiredOrUsed) {
setShowExpiredMessage(true);
diff --git a/autogpt_platform/frontend/src/components/auth/ExpiredLinkMessage.tsx b/autogpt_platform/frontend/src/components/auth/ExpiredLinkMessage.tsx
index 69ac71223e..4d08f44397 100644
--- a/autogpt_platform/frontend/src/components/auth/ExpiredLinkMessage.tsx
+++ b/autogpt_platform/frontend/src/components/auth/ExpiredLinkMessage.tsx
@@ -19,8 +19,7 @@ export function ExpiredLinkMessage({
Your reset password link has expired or has already been used