GoogleCloudPlatform/microservices-demo · error · InvalidCreditCard
InvalidCreditCard
Error message
InvalidCreditCard
What it means
InvalidCreditCard is thrown by the checkout charge() function in src/paymentservice/charge.js when the simple-card-validator reports that the submitted credit card number does not pass its Luhn/format validity check (cardInfo.getCardDetails().valid is false). It signals a malformed or bogus card number in the ChargeRequest, not a payment network problem. The error extends CreditCardError with gRPC-style code 400 (Invalid Argument).
Source
Thrown at src/paymentservice/charge.js:70
}
}
/**
* Verifies the credit card number and (pretend) charges the card.
*
* @param {*} request
* @return transaction_id - a random uuid.
*/
module.exports = function charge (request) {
const { amount, credit_card: creditCard } = request;
const cardNumber = creditCard.credit_card_number;
const cardInfo = cardValidator(cardNumber);
const {
card_type: cardType,
valid
} = cardInfo.getCardDetails();
if (!valid) { throw new InvalidCreditCard(); }
// Only VISA and mastercard is accepted, other card types (AMEX, dinersclub) will
// throw UnacceptedCreditCard error.
if (!(cardType === 'visa' || cardType === 'mastercard')) { throw new UnacceptedCreditCard(cardType); }
// Also validate expiration is > today.
const currentMonth = new Date().getMonth() + 1;
const currentYear = new Date().getFullYear();
const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard;
if ((currentYear * 12 + currentMonth) > (year * 12 + month)) { throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year); }
logger.info(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`);
return { transaction_id: uuidv4() };
};
View on GitHub (pinned to 72ba613a05)
Solutions
- Send a Luhn-valid card number with correct length, e.g. '4012-8888-8888-1881' (VISA) or '5555-5555-5555-4444' (MasterCard)
- Validate the card number client-side (or at the caller) with simple-card-validator before calling Charge
- Check that the credit_card_number field is actually populated and not shifted/misaligned in your request construction
- Remember the number must also be VISA/MasterCard to pass the next check
Example fix
// before
await paymentClient.Charge({ amount, credit_card: { credit_card_number: '1234-5678-9012-3456', ... } });
// after
await paymentClient.Charge({ amount, credit_card: { credit_card_number: '4012-8888-8888-1881', ... } }); Defensive patterns
Strategy: validation
Validate before calling
const cardValidator = require('simple-card-validator');
function isChargeableCard(cardNumber) {
if (typeof cardNumber !== 'string' || !cardNumber.trim()) return false;
const details = cardValidator(cardNumber).getCardDetails();
return details.valid === true;
}
if (!isChargeableCard(req.credit_card.credit_card_number)) {
return res.status(400).json({ error: 'Invalid card number' });
} Type guard
function isValidCardNumber(v) {
return typeof v === 'string' && /^\d{12,19}(-?\d{4})+$/.test(v.replace(/-/g, '').length ? v : v) && require('simple-card-validator')(v).getCardDetails().valid === true;
} Try / catch
try {
const result = await paymentClient.Charge(chargeRequest);
} catch (err) {
if (err.message === 'InvalidCreditCard' || /invalid/i.test(err.message)) {
return res.status(400).json({ error: 'Card number is not valid; please re-enter it.' });
}
throw err;
} Prevention
- Validate card numbers with simple-card-validator on the client before calling Charge
- Use known-good test card numbers (VISA 4012-8888-8888-1881, MC 5555-5555-5555-4444) in tests
- Never send empty or placeholder card numbers to the payment service
- Capture the card number field length/format at input time with Luhn checking
When it happens
Trigger: Calling ChargeRequest via PlaceOrder with a credit_card_number that is not a syntactically valid card number (fails Luhn or length rules per simple-card-validator), e.g. a random digit string, a truncated number, or a placeholder like '0000-0000-0000-0000'.
Common situations: Test harnesses or load generators sending dummy card numbers; forms/skipped client-side validation passing raw user input; data migrations with corrupted card fields; unit tests forgetting that the demo checkout still validates card syntax.
Related errors
- UnacceptedCreditCard
- ExpiredCreditCard
- could not charge the card: %+v
- FAILED_PRECONDITION
- FAILED_PRECONDITION
AI-assisted analysis of GoogleCloudPlatform/microservices-demo@72ba613a05 (2026-09-02).
Data as JSON: /api/errors/ee39b19ba8613342.
Report an issue: GitHub.