TheAlgorithms/JavaScript · error · Error

${creditCardString} is an invalid credit card number because

Error message

${creditCardString} is an invalid credit card number because it fails the Luhn check.

What it means

Thrown by validateCreditCard() when the string passes type, NaN, length, and prefix checks but fails the Luhn checksum (luhnValidation returns false). The Luhn algorithm sums digits with every second digit doubled-and-split; failing means a typo or fabricated number. Generic Error, not TypeError.

Source

Thrown at String/ValidateCreditCard.js:57

  }

  const errorMessage = `${creditCardString} is an invalid credit card number because `
  if (isNaN(creditCardString)) {
    throw new TypeError(errorMessage + 'it has nonnumerical characters.')
  }
  const creditCardStringLength = creditCardString.length
  if (!(creditCardStringLength >= 13 && creditCardStringLength <= 16)) {
    throw new Error(errorMessage + 'of its length.')
  }
  if (
    !validStartSubString.some((subString) =>
      creditCardString.startsWith(subString)
    )
  ) {
    throw new Error(errorMessage + 'of its first two digits.')
  }
  if (!luhnValidation(creditCardString)) {
    throw new Error(errorMessage + 'it fails the Luhn check.')
  }

  return true
}

export { validateCreditCard }

View on GitHub (pinned to 5c39e87a9a)

Solutions

  1. Verify the number against an independent Luhn tool; recompute the check digit if generating test data.
  2. Have the user re-enter the number; surface a 'Please check your card number’ message.
  3. When generating fixtures, derive the last digit using the Luhn algorithm so the number is valid.
  4. Confirm sanitization did not drop or duplicate a digit before validation.

Example fix

// before
validateCreditCard('4111111111111112') // wrong check digit

// after
validateCreditCard('4111111111111111') // Luhn-valid Visa test number
Defensive patterns

Strategy: validation

Validate before calling

function luhnValid(s) {
  let sum = 0, alt = false
  for (let i = s.length - 1; i >= 0; i--) {
    let d = parseInt(s[i], 10)
    if (alt) { d *= 2; if (d > 9) d -= 9 }
    sum += d; alt = !alt
  }
  return sum % 10 === 0
}
// call luhnValid(digits) before validateCreditCard to pre-empt

Type guard

const passesLuhn = (s) => typeof s === 'string' && /^\d+$/.test(s) && luhnValid(s)

Try / catch

try { validateCreditCard(card) } catch (e) { if (/Luhn check/.test(e.message)) { /* ask user to re-check the number */ } else throw e }

Prevention

When it happens

Trigger: Calling validateCreditCard('49927398716') would fail length first; for a length- and prefix-valid number like '4111111111111112' (last digit changed), luhnValidation returns false and this throws. Transposing two adjacent digits, or flipping a single digit, usually breaks Luhn.

Common situations: User mistyped a digit; generated test numbers without computing the Luhn check digit; copy-paste that dropped or duplicated a digit; intentionally using an invalid number to test the error path.

Related errors


AI-assisted analysis of TheAlgorithms/JavaScript@5c39e87a9a (2026-08-13). Data as JSON: /api/errors/c96ac1e3660024e1. Report an issue: GitHub.