Research note · August 11, 2026
Three ways a spelling correction can be confidently wrong.
Building Google-style spelling correction for LinkedCulture surfaced three separate bugs, each one a plausible-looking answer that was actually wrong. None of them showed up until real misspellings were thrown at it.
linkedculturesearchspellingcorrectionopensearchengineeringsemanticsearch
The Met's semantic search writeup mentioned, almost in passing, that their new search offers as-you-type suggestions: type a few letters and it routes you toward an artist, an object type, a place, rather than making you finish typing a guess. That's a small feature with a real payoff, so LinkedCulture got its own version: type "remb" into the search box and a dropdown offers "Rembrandt van Rijn, 1,027 objects" before you've finished the word.
That part went fine. The harder problem showed up next, when the obvious follow-up question got asked: what happens when someone just can't spell the name at all?
The first version, and the first bug
"Did you mean...?" is a solved problem in the sense that every major search engine has one. The standard building block, OpenSearch's term suggester, compares a misspelled word against everything actually indexed and returns the closest matches by edit distance, how many single-character changes separate two words.
The first version worked immediately for the easy case. Type "rembrant" and it correctly offers "rembrandt." Type "vermear" and it offers "vermeer." That felt like enough to ship.
Then came the test that broke it: "renbrend." Three characters off from "rembrandt," which is a lot for a human to misspell but not unreasonable if you genuinely don't know how the name is spelled. The suggester's answer: "reverend."
Not a crash, not an empty result, an actual answer with actual confidence behind it. "Renbrend" and "reverend" happen to be almost the same edit distance apart as "renbrend" and "rembrandt," and by the suggester's math, "reverend" scored slightly closer. A person who can't spell "Rembrandt" is not going to be reassured by a clickable link to "reverend."
The second version, and the second bug
The fix was to add a phonetic check. Two words can be a few characters apart on paper and still be pronounced nothing alike, "renbrend" and "reverend" are one such pair, and a phonetic encoding (double metaphone, the same family of algorithm postal services use to catch misspelled street names) catches that a plain character count misses. Cross-check every edit-distance candidate against how the original word actually sounds, and reject anything that doesn't sound close, no matter how good its character-count score looks.
That fixed "renbrend" correctly to "rembrandt." It also created a second, unrelated bug in the process of fixing the first.
The phonetic check needed real words to check against, so it needed its own dictionary: every creator name and title in the catalog, broken into individual words, each one run through the phonetic algorithm and stored as (sound, word, how often that word actually appears). 139,833 entries, built once from Postgres in about forty seconds. Straightforward enough.
The bug was in how ties got broken. "Vermear," a plausible typo for "Vermeer," phonetically matches "Vermeer" exactly. It also happens to phonetically resemble "vermaak," an unrelated Dutch word that shows up constantly in the corpus. Choosing by pure word frequency, since a more common word is usually the safer bet, picked "vermaak," the wrong answer, over "Vermeer," the right one, because "vermaak" simply appears more often across half a million records than any one painter's name does.
Frequency alone was the wrong tiebreaker for the same reason edit distance alone was: neither one is actually measuring "does this sound like what the person meant." The fix was to require a large margin, at least ten times more frequent, before letting popularity override a strong phonetic match. A 1.7x edge, which is what "vermaak" had, isn't real evidence. A 2,800x edge, which showed up in a different case (a rare word can also just be a rare word, "portrait" is that much more common than "portrat," a French variant few English speakers would ever type on purpose), is.
The third version, and the bug that was already there
Fixing the tiebreak surfaced a third problem, this one older than either fix, just never triggered before: a search for "toulouse," spelled correctly, got quietly "corrected" to "dailles," an unrelated French word. Nothing about the phonetic layer thought "toulouse" needed fixing at all. The bug was upstream of it: the code had no way to tell "this word doesn't exist in the catalog" apart from "this word exists but has no close typo-neighbors," and "toulouse" fell into the wrong bucket. The system doesn't correct a word that's already in the catalog anywhere, but it needed an explicit check for that, and until this pass it didn't have one.
Three fixes, each one closing a gap the previous fix opened or exposed. None of the three were visible from reading the code. Every one of them only showed up by throwing real misspellings at the system and reading the actual output, not by reasoning about what the algorithm should do in theory.
Where it landed
The current version:
- Common typos ("rembrant," "renbrandt," "rembrent") correct cleanly, and multiple misspelled words in one search box get fixed independently: "rembrant self portrate" comes back as "rembrandt self portrait," not just the first error caught.
- Bad spelling, not just typos ("mikelanjelo") now gets caught by the phonetic layer, which plain edit-distance checking can't reach past a certain point, it caps at two character changes by design.
- A confident wrong answer is worse than no answer. Every fix in this post exists because a plausible-but-wrong suggestion is a worse experience than admitting nothing close was found, not because the feature needed to catch every conceivable typo.
One honest gap remains: "vangoh," run together with no space, still gets nothing. That's a different kind of mistake, a missing word boundary rather than a misspelled word, and it isn't fixed here.
None of this needed a new piece of infrastructure. The phonetic matching runs as plain application code, not a database plugin, specifically so it wouldn't require touching the search engine's core service to ship it. The whole thing lives beside the search index, not inside it.
This is part of a short series responding to the Met's semantic search launch: the first note covered what changes when that same capability spans ten institutions instead of one.
Explore it: https://linkedculture.org/