DEV Community

Vin Lookup
Vin Lookup

Posted on

Designing Error States for VIN Lookup UIs: Invalid, Incomplete, and Ambiguous Decodes

VIN forms look simple: seventeen characters in, structured fields out. The hard part is what you show when the input is wrong, partial, or only half-supported by the API.

Three failure classes

Invalid: fails format or check digit. Do not call the network yet. Explain what failed (length, illegal character, check digit).

Incomplete: user is still typing. Show progress (13/17) without scary errors.

Ambiguous / sparse: API returns 200 with many blank fields. That is not a crash. Say what you know and what you do not.

Soft vs hard fail

Hard fail: block submit for impossible VINs.
Soft fail: allow decode attempts that may return sparse data, but label confidence.

type VinGate =
  | { ok: true; vin: string }
  | { ok: false; reason: "length" | "charset" | "checkDigit" };

function gateVin(raw: string): VinGate {
  const vin = raw.trim().toUpperCase();
  if (vin.length !== 17) return { ok: false, reason: "length" };
  if (/[IOQ]/.test(vin)) return { ok: false, reason: "charset" };
  // check digit omitted for brevity
  return { ok: true, vin };
}
Enter fullscreen mode Exit fullscreen mode

Copy that helps buyers

Avoid "Error 500" language. Prefer:

  • "This VIN fails the check digit. Re-type from the dash plate."
  • "We decoded make and model year. Trim and engine came back blank from NHTSA."
  • "A free decode is not a title or salvage report."

Marketplace embed pattern

If you embed VIN checks in listings, never mark a listing "verified" on decode alone. Use decode as a consistency check against the seller's claimed year/make/model.

I maintain VIN Lookup, a free VIN decode based on NHTSA data.

Top comments (0)