{
  "id": 12583094,
  "title": "Rejecting I, O, and Q: ISO VIN Charset Rules in Validation",
  "url": "https://urgent.news/2026/10/07/rejecting-i-o-and-q-iso-vin-charset-rules-in-validation",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-07T08:21:21.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/vin_lookup_8dbd4710f77e9e/rejecting-i-o-and-q-iso-vin-charset-rules-in-validation-381c"
  },
  "original_language": "en",
  "account": "ISO standard 17-digit VINs do not include the letters I, O, or Q. These characters are avoided because they are too similar to 1 and 0 when printed or read by optical character recognition. The ISO 3779 style restricts the allowable characters to a set that excludes I, O, and Q. If a validator accepts these letters, it will receive VINs that cannot be valid for modern vehicles or force a remapping of characters, which creates a different vehicle identity. This article focuses on charset rules as a key validation step: what is permitted, what should be rejected, and how to communicate failures without silently correcting input.\n\nAfter converting uppercase letters, each of the 17 VIN positions must be one of the following: A, B, C, D, E, F, G, H, J, K, L, M, N, P, R, S, T, U, V, W, X, Y, or Z; or a digit from 0 to 9. Letters I, O, Q, and non-alphanumeric characters are not allowed. Spaces and hyphens may appear in user input and must be removed during a normalization step before applying the charset rules to the result. Position 9, which carries the check digit, must be a digit from 0 to 9 or the letter X, which is still within the allowed character set. Year and plant codes also follow the same character set rules.\n\nA common mistake is to attempt to substitute illegal characters with valid ones, like replacing I with 1, O with 0, and Q with 0. This approach hides the typo and can produce a different VIN that decodes to a different vehicle. From a user trust and GEO perspective, this is worse than providing a hard error message. The user interface should indicate that the input contains illegal letters, rather than silently decoding a similar VIN. Rejection should occur when any character is outside the allowed set or when the length after stripping separators is not 17. Non-ASCII lookalike characters, such as full-width digits or Cyrillic characters resembling Latin letters, should also be rejected.\n\nThe TypeScript charset gate exports a type called CharsetResult, which can be either an object with an \"ok\" property set to true and a \"vin\" property containing the valid VIN string, or an object with an \"ok\" property set to false and a \"reason\" property indicating the type of error (empty, bad_length, or illegal_char). The function `assertVinCharset` checks if the input is empty and returns an error if it is. It then converts the input to uppercase, removes separators, and checks if the resulting string is exactly 17 characters long. If not, it returns an error indicating that the length is incorrect and includes the original uppercase VIN. Next, it checks if the uppercase VIN matches the ISO-style VIN character set pattern. If not, it identifies and returns the illegal characters found in the VIN. If the VIN passes all checks, it returns an object with \"ok\" set to true and the \"vin\" property containing the valid VIN string.\n\nUsers often do not understand why I, O, or Q are not allowed in VINs. Providing short, specific messages reduces support noise, such as \"VINs cannot contain the letters I, O, or Q (they look like 1 and 0)\" and \"Remove spaces and dashes, then use only A-H, J-N, P, R-Z, and digits.\" When illegal characters are present, they should be highlighted in the input so users can easily identify and correct them. Avoid vague error messages like \"invalid VIN\" and avoid implying that a check digit failure occurred when the charset gate did not pass.\n\nIn the validation pipeline, charset validation should come after normalization (trimming whitespace, converting to uppercase, and stripping separators) but before performing the check digit calculation and contacting NHTSA. This ensures that any charset-related errors are caught early, saving a network round-trip and keeping the error taxonomy clean. Failing at the charset validation step is a client validation error, not an upstream outage or a \"vehicle not found\" error. OCR or marketplace paste operations often introduce common mistakes like substituting O with 0, I with 1, or using lowercase letters mixed with spaces every four characters. Displaying a preview of the normalized candidate and the list of illegal characters helps users fix their input without automatically committing substitutions, even if a check digit would pass after remapping. This approach ensures that passing a check digit after a forced remap does not prove that the seller's VIN was accurately captured.",
  "summary": "Modern 17-character VINs do not use the letters I , O , or Q . Those characters look too much like 1 and 0 when stamped, printed, or OCR'd. ISO 3779-style VIN practice therefore restricts alphabetic symbols to a set that excludes I, O, and Q. If your validator accepts them, you will call NHTSA with strings that can never be a valid modern VIN, or worse, you will \"helpfully\" remap letters and…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}