Typos, and which retriever forgives them

A warehouse operator searches an equipment manual for “hydralic leak on the forlift”. Lexical retrieval returns nothing useful — neither misspelled token exists in the corpus, so there is nothing to score. Dense retrieval returns forklift hydraulics material, slightly out of order.

That asymmetry is the useful part. Typos are the one query defect where the two signals differ predictably, and knowing which one degrades gracefully tells you where to spend the fix.

Query: "hydralic leak on the forlift"

LEXICAL (BM25)                            DENSE (vector)
1. Leak testing procedure             ~   1. Forklift hydraulic system       ✓
2. Leak detection sensors             ✗   2. Hydraulic leak troubleshooting   ✓
3. Oil leak reporting form            ~   3. Forklift daily inspection       ~
4. Coolant leak symptoms              ✗   4. Hydraulic fluid specification    ~
5. Leak-down test intervals           ✗   5. Leak testing procedure          ~

Lexical retrieval scored on the one correctly spelled content word, “leak”, and returned everything in the corpus that leaks. Dense retrieval read a subword sequence close to the correct one and landed approximately right.

Why lexical matching fails discontinuously

Term matching is exact after analysis. forlift and forklift are different strings, they analyse to different tokens, they occupy different posting lists, and there is no partial credit. A single transposed character removes the term from the query entirely — a typo does not weaken a lexical match, it deletes it.

Stemming does not help, because stemmers strip suffixes rather than repair spellings. The analyser is working correctly and the term simply is not there.

The damage is proportional to how much of the query’s discriminating power sat on the misspelled word. Misspell a common word and the loss is negligible. Misspell the rare term that made the query answerable — the product name, the identifier, the technical term — and you have removed the only high- weight term in the query. Which means typo damage on the lexical side is worst precisely on the query class where lexical retrieval was the signal that worked.

Why dense matching degrades gradually

An embedding model tokenises into subword pieces. A misspelled word fragments differently from the correct one, but the fragments overlap substantially — for lift against fork lift — and the resulting vector lands near, not far. Combined with the rest of the query’s context, the retrieval is usually approximately right.

Three limits on that tolerance, all worth knowing:

It is not error correction. The vector is near the right place, not at it, so ranking degrades even when the right document is retrieved. A misspelled query with a reranker after it recovers better than one without, because the cross-encoder reads both strings and can tolerate the noise more intelligently.

Short queries lose their context. A misspelled single-word query has nothing to steady it, and the resulting vector may be anywhere.

Identifiers get no benefit. TX-9910 misspelled as TX-9190 is a valid different identifier, and it is close in the embedding space to the correct one for the same reason all identifiers are close to each other. Dense retrieval’s tolerance comes from meaning being preserved under small perturbations, and an identifier has no meaning to preserve. This is the case where both signals fail and neither degrades gracefully.

The three repairs

Fuzzy term matching in the lexical index. Match terms within a small edit distance of the query term. Effective for ordinary words and it comes with costs that grow quickly: the query touches more posting lists, so it is slower, and a small edit distance on a short word admits genuinely different words — in a corpus of part numbers, edit-distance matching is actively dangerous. Restrict it to tokens above a length threshold and never apply it to anything matching an identifier pattern.

Spelling correction before retrieval. Correct the query, then search normally. Better ranking than fuzzy matching, because the corrected term carries its true corpus statistics rather than a distance-discounted approximation. The correction dictionary must be built from your corpus, not from general English — a general corrector will “fix” your domain vocabulary into ordinary words and destroy the query. This is the single most common way a spelling stage makes search worse.

Do nothing, and rely on the dense signal. Legitimate, and cheaper than either. In a hybrid pipeline the dense list already covers the ordinary-word case, and if your query log shows typos concentrated in ordinary words, fusion is already handling them. Verify before building anything.

A fourth option that is not a repair but often the best move: surface the correction to the user. Search with the corrected query, show what you corrected, let them undo it. That converts a silent guess into an interaction, which is the only version that cannot be confidently wrong.

The case that needs deliberate handling

Misspelled identifiers, because everything above fails on them.

Fuzzy matching on TX-9190 finds TX-9910 and also TX-9110 and TX-9190-B, with no basis for preferring any of them. Dense retrieval finds the family. Spelling correction has no dictionary entry. The correct behaviour is not a better ranking — it is telling the user that the identifier they typed does not exist and offering the near ones.

That is an exact-lookup interaction rather than a retrieval one, and it wants a dedicated path: detect the identifier pattern, look it up structurally, and on a miss return the nearest valid identifiers by string distance with an explicit “did you mean” rather than blending them into a ranked list of documents. This is the same argument as routing identifier queries away from similarity search, applied to the case where the identifier is wrong.

Telling whether it’s your problem

Typo rates vary enormously by interface, and the variation is larger than most teams assume. Mobile free-text search over industrial vocabulary has a high rate; a desktop tool used by specialists typing familiar terms has a low one. So measure rather than assume.

The measurement: take a sample of queries with no clicked result, and for each, check whether any query token is absent from the corpus vocabulary entirely. An out-of-vocabulary token in a failing query is a strong typo signal, and it is computable from the index without labelling anything.

Then split those by whether the out-of-vocabulary token is identifier-shaped. The two halves need different fixes, and the split is usually lopsided in a way that decides your priorities immediately. If nearly all are ordinary words, a corpus-derived corrector is your intervention. If nearly all are identifiers, no amount of fuzzy retrieval will help and you need the lookup path.