Why a blank form input can bypass required field validation
Most required-field checks test length, not content. The common implementation is value.trim().length > 0, and a character that survives the trim satisfies it while displaying nothing.
The check was written to catch a genuinely empty field, which is the case it handles correctly. It was not written to establish that a human supplied a meaningful answer, and it cannot tell the difference.
This is why "field cannot be empty" persists when you press the spacebar. U+0020 has the Unicode property White_Space=Yes, so trim() removes it and the trimmed value is still empty. A character with White_Space=No is not removed, so the length test passes.
Where it fails
Four kinds of validation reject it, and they are increasingly common.
- Trimming validators. A form that trims before checking removes every
Zscharacter, so U+00A0 and every space variant fail. OnlyCf,LoandSocharacters survive. - Shape validation. A field expecting an email address, a phone number or a date checks the pattern, not the presence. No invisible character matches those patterns.
- Server-side validation. A client-side check is a convenience. A server that revalidates sees the codepoint plainly, and increasingly strips it.
- Non-text inputs. A required radio group, checkbox or dropdown has no text field to paste into. Nothing about invisible characters applies.
Google Forms and survey responses
A required short-answer question accepts an invisible character; a validated one does not. Google Forms checks for a non-empty response rather than for visible content.
A blank text survey response reaches the spreadsheet as a cell that looks empty and is not, which creates the same downstream problem described on the Excel guide — the value parses as text, sorts oddly and breaks a COUNTIF against an empty string.
Worth being direct about the consequence. A required survey question is usually required because the answer is the point of collecting it. A blank submission is not a neutral act toward whoever is reading the results — it is a row of data that looks answered and is not.
How to close it in your own validation
To reject invisible input, normalize and strip before you measure length. Checking the trimmed length alone will always be defeatable, because trimming only handles the Zs category.
In JavaScript:
- Strip format characters —
value.replace(/\p{Cf}/gu, "") - Fold odd spaces —
.replace(/\p{Zs}/gu, " ") - Then
.trim()and check the length
Two cautions carry over from the detector. U+200D Zero-Width Joiner is structural inside emoji, and U+200C Zero-Width Non-Joiner is orthographically required in Persian, Hindi and Bengali. Stripping all Cf characters from free-text fields breaks both. Apply the strict rule to identifiers and short answers, not to a comments box.
The stronger fix is to validate the shape of the answer rather than its presence. A field that requires a minimum word count, a matching pattern or a value from a known set cannot be satisfied by a character that carries no information.
When this is ordinary work
Testing your own form is exactly what this technique is for. An invisible character is a useful fixture: it proves whether a sanitiser handles non-ASCII blank input before a real user finds out that it does not.
Three uses are unambiguous. Testing validation on a form you own or maintain. Filling a field that is technically required and genuinely not applicable, where no other option exists. Building QA fixtures that exercise the empty-but-not-empty case.
Submitting blank answers to someone else's research, or to a form where the answer carries consequences for another person, is a different thing wearing the same technique. The codepoint is neutral; what you do with it is not.