medusajs/medusa · error · MedusaError

Verification code has expired

Error message

Verification code has expired

What it means

The verification code exists and is unused, but requested_at + TTL is in the past, so the code is expired and confirmation is rejected. TTL comes from the token provider's getTokenTtlMs_().

Source

Thrown at packages/modules/auth/src/providers/verification/token.ts:139

        "Verification code is invalid or already used"
      )
    }

    if (
      data.code_provider &&
      data.code_provider !== verification.code_provider
    ) {
      throw new MedusaError(
        MedusaError.Types.NOT_ALLOWED,
        `Verification code does not belong to provider "${data.code_provider}"`
      )
    }

    const expiresAt =
      new Date(verification.requested_at).getTime() + this.getTokenTtlMs_()

    if (expiresAt <= Date.now()) {
      throw new MedusaError(
        MedusaError.Types.NOT_ALLOWED,
        "Verification code has expired"
      )
    }

    return await this.authVerificationService_.update(
      {
        id: verification.id,
        verified_at: new Date(Date.now()),
      },
      sharedContext
    )
  }

  protected getTokenTtlMs_(): number {
    return getVerificationTokenTtlMs(this.options_.ttl_seconds ?? 900)
  }
}

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Trigger a new verification request to get a fresh code
  2. Increase the TTL configuration if legitimate users routinely exceed it
  3. Start the expiry timer from when the email is actually sent, not queued, if delivery is slow
Defensive patterns

Strategy: fallback

Validate before calling

// show countdown client-side based on requested_at + TTL
const expired = Date.now() > requestedAt + TTL_MS
if (expired) await resendCode()

Try / catch

try { await confirm(...) } catch (e) { if (e.message.includes('expired')) { await resendCode() } throw e }

Prevention

When it happens

Trigger: Confirming a verification more than the configured TTL (commonly 10–15 minutes) after it was requested; also triggered by long-delayed queue processing or a user returning to a stale form.

Common situations: User waits too long before entering the code; TTL misconfigured very low; email delivery delays pushing real elapsed time past the window.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/0cfc843ba8b7253f. Report an issue: GitHub.