All findings · Lucene finding · LFV-850 · romaji-map-missing-extended-katakana-rows

Kuromoji completion: `romaji_map.txt` has no rows for チェ, イェ, ツァ-ツォ, ディ, デュ or ウォ, so typing `chekku`, `ye` or `tsa` suggests nothing

With JapaneseCompletionAnalyzer, typing chekku, ye or tsa suggests nothing for チェック, イェール or ツァー, while shea finds シェア: the bundled table romaji_map.txt has no row for these kana, so チェック is indexed only as tixekku and chixekku. Every release since 9.0.0.

Summary

Priority
Low, rank 507The opt-in completion table has no rows for loanword kana such as チェ, イェ, ツァ, ディ and ウォ, so those suggestions are lost silently but only when the loanwords are typed in raw romaji, which puts it with the Kuromoji romanization rare-input rows right after LFV-605.
Impact
silent wrong results
Since
9.0.0 (2021), the first release with the completion filterintroduced 2021-09-17 · about 5 years
Affected
9.0.0 to 10.6.0 and main
Status
documented
Found by
comparison with ICU4J's Katakana-Latin output, then a table-consistency check and a bounded-exhaustive check of the romanizer

AI-assisted page: this finding was first signalled by code reading or testing and then checked with AI tools; the checks it went through, and what each found, are under Prior reports, history and checks. Not yet triaged by a human. Snapshot of 2026-11-06.

The finding in 30 seconds

The completion filter adds romaji tokens to each Japanese word, read from the bundled table romaji_map.txt, so a suggester can match Latin-letter input.

Summary card of the bug in four panels. Panel 1, what you do: index チェック with JapaneseCompletionAnalyzer and type chekku, expecting [チェック]; the javadoc lists modified Hepburn as supported. Panel 2, what Lucene does: there is no row チェ, so チェック is indexed only as tixekku and chixekku; typed chekku and indexed chixekku differ at the 3rd letter, so the suggester returns nothing. Panel 3: romaji_map.txt has the sibling rows シェ she, ジェ je, ウィ wi, ウェ we, ティ thi, テュ thu and ッイェ yye, but no row for チェ, イェ, ツァ-ツォ, ディ, デュ or ウォ, which fall back to small-vowel spellings. Panel 4, executed on main with assertions on and off: the typed spellings find nothing, the fallback spellings, the kana and the siblings are still found, and the 9-row table fix makes all of them found.
Summary card: what the application does, how チェック is indexed (チ + small ェ gives only tixekku and chixekku), why chekku is not a prefix of either, the sibling rows that exist next to the nine missing ones, and the executed result. Select the still to open it at full size. Generated with AI, checked against the code.
  1. You index チェック, イェール and ツァー as suggestions with JapaneseCompletionAnalyzer, plus the control シェア, and query with PrefixCompletionQuery.
  2. You expect chekku to suggest チェック, as shea suggests シェア: the javadoc lists modified Hepburn, where チェ is che, イェ ye and ツァ tsa, and the open-source Mozc input-method table accepts the same keystrokes.
  3. Instead chekku, ye and tsa return no suggestion, with no error. So do the input-method keystrokes dhisuku (ディスク), dhuetto (デュエット) and whokka (ウォッカ).
  4. Why: the table has シェ,sye,she and even ッイェ,yye, but no row for チェ or イェ. So チェ is split into チ (ti, chi) plus a small ェ (xe), and チェック becomes [チェック, tixekku, chixekku]; che is a prefix of neither.
  5. Kana typed through an input method (ちぇ, ちぇっk) still match, because both sides use the same split. Input-method users miss it only while a romaji prefix is pending: y, dh, w and wh (two keystrokes before うぉ), or ty/cy if they type ちぇ as tye/cye.

Who is affected

Applications using the opt-in JapaneseCompletionAnalyzer or JapaneseCompletionFilter (search servers expose it as kuromoji_completion), with default settings, in every release since 9.0.0. It hits loanwords with チェ, イェ, ツァ-ツォ, ディ, デュ or ウォ, such as チェック or ウォッカ. People typing raw romaji lose the suggestion; input-method users only while a romaji prefix such as y, dh, w/wh or ty/cy is pending.

Mechanism, terms and numbers632 words

Kuromoji's completion analyzer (JapaneseCompletionAnalyzer, JapaneseCompletionFilter) indexes each Japanese word together with its romaji spellings, so an autocomplete can match Latin-letter input. Its bundled table romaji_map.txt has rows for loanword sounds such as シェ (she), ジェ (je), ティ (thi), ウィ (wi) and even the doubled ッイェ (yye), but none for チェ, イェ, ツァ/ツィ/ツェ/ツォ, ディ, デュ or ウォ. Those kana are spelled out as base kana plus a small vowel (チェック → tixekku, chixekku; イェール → ixeーru; ツァー → tuxaー, tsuxaー), so typing the Hepburn spellings chekku, ye or tsa, or the input-method keystrokes dhi, dhu or who, suggests nothing, with no error. Kana typed through an input method still match. It affects every release from 9.0.0 to 10.6.0 and main; the fix is data only.

Terms

  • Extended katakana: two-kana units for sounds of loanwords, written with a small vowel: チェ (che, as in チェック "check"), イェ (ye, イェール "Yale"), ツァ (tsa, ツァー "tsar"), ディ (ディスク "disk"), デュ (デュエット "duet"), ウォ (ウォッカ "vodka").
  • Romanizations: modified Hepburn writes チェ, イェ, ツァ/ツィ/ツェ/ツォ as che, ye, tsa/tsi/tse/tso. The open-source Mozc input-method table accepts the same keystrokes and maps dhi, dhu, who to でぃ, でゅ, うぉ; a small vowel alone can be typed with x (xe → ぇ).
  • JapaneseCompletionFilter: for each word it emits the word itself and every romaji spelling of its katakana reading at the same position (generateOutputs, JapaneseCompletionFilter.java:217-233). The spellings come from romaji_map.txt, where each row maps a key to its spellings (for example シェ,sye,she); KatakanaRomanizer matches the reading longest key first and combines the spellings of the matched rows (KatakanaRomanizer.java:103-169). The javadoc lists "(modified) Hepburn-shiki, Kunrei-shiki (Nihon-shiki) and Wāpuro shiki" as supported (:41-42).
  • Completion query: PrefixCompletionQuery suggests a word when the typed text, after the QUERY-mode analyzer, is a prefix of one of the word's indexed forms. Raw romaji such as chekku comes out as the single token chekku.

The bug

kanarow todayspellings produced (fallback)sibling rows that exist
チェnonetixe, chixe (:47 チ,ti,chi + :317 ェ,xe):35 シェ,sye,she, :44 ジェ,zye,je, :51-53 チャ / チュ / チョ
イェnoneixe (:8 イ,i + ェ):251 ッイェ,yye (the doubled form)
ツァ, ツィ, ツェ, ツォnonetuxa, tsuxa ... (:48 ツ,tu,tsu + :314-318)none for ツ
ディ, デュnonedexi, dexyu (:57 デ,de + small vowel):156 ティ,thi,texi, :159 テュ,thu,texyu
ウォnoneuxo (:9 ウ,u + :318 ォ,xo):114 ウィ,wi, :116 ウェ,we

The numbers

Index-side tokens on main: チェック → [チェック, tixekku, chixekku], イェール → [イェール, ixeーru], ツァー → [ツァー, tuxaー, tsuxaー], ディスク → [ディスク, dexisuku], デュエット → [デュエット, dexyuetto], ウォッカ → [ウォッカ, uxokka]; compare シェア → [シェア, syea, shea]. Typed chekku, ye, tsa, dhisuku, dhuetto, whokka: no suggestion. Typed shea, thi, wiki, chixekku, and the kana ちぇ, ちぇっk, いぇ, つぁ, でぃ, うぉ: found. Typing raw romaji, ch and ts still find チェック and ツァー, but che, tsa, y, dh, wh, ty and cy find nothing, and w finds ウィキ but not ウォッカ.

The code follows the table: romanize() matched a separately coded longest-match model of the same table, bounded-exhaustively, on all 1,830,854 inputs of length up to 3 and on 57,289,761 inputs of length 4 (0 mismatches; a shortest-match mutant was caught). That shows implementation and model agree over the tested domain; the gap itself is in the data rows.

Exposure and likelihood265 words
  • Who. Applications that build Japanese autocomplete with JapaneseCompletionAnalyzer or JapaneseCompletionFilter (also through the analysis SPI as japaneseCompletion; search servers built on Lucene expose it as a kuromoji_completion token filter). Opt-in; it reproduces with the default constructors, the standard INDEX/QUERY configuration and no user dictionary.
  • What triggers it. Loanwords whose reading has チェ, イェ, ツァ/ツィ/ツェ/ツォ, ディ, デュ or ウォ, typed as raw romaji: チェック chekku, イェール ye..., ツァー tsa..., and with the input-method keystrokes ディスク dhi..., デュエット dhu..., ウォッカ who.... No special input, no scale. How often such words occur was not measured.
  • Two groups of users. People who type romaji directly lose the suggestion for these words; raw romaji is a designed input (the introducing issue wants 桜 suggested for "さ", "サ" or "sa"). Input-method users lose it only while a romaji prefix is pending, before the kana appear: y (before いぇ), dh (before でぃ/でゅ), w and then wh (before うぉ, two keystrokes), and ty/cy if they type ちぇ as tye/cye (the Mozc table maps both).
  • What still works. Kana committed or composed through an input method (ちぇ, ちぇっk, いぇ, つぁ, でぃ, うぉ) and the explicit small-vowel spellings (chixe, ixe, tsuxa, dexi, uxo).
  • Silent. No exception, no log line: the suggestion list is just shorter.
  • After a fix the index-side tokens change, so existing suggest fields must be reindexed. The query side needs no change; QUERY mode loads the same table, so kana queries gain the new spellings too (ちぇ → [ちぇ, tye, che, cye, tixe, chixe]).

Minimal repro

The test shows that Kuromoji's romaji_map.txt has no row for チェ (it has シェ and チャ), so チェ gets only the small-vowel fallback romaji.

TestRomajiMapChe.java (JUnit test)31 lines
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.lucene.analysis.ja.completion;

import java.util.List;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.lucene.util.CharsRef;

public class TestRomajiMapChe extends LuceneTestCase {

  public void testCheRomanizesToChe() {
    List<CharsRef> actual = KatakanaRomanizer.getInstance().romanize(new CharsRef("チェ"));
    // expected che (as シェ -> she, チャ -> cha); actual [tixe, chixe] (no row for チェ)
    assertTrue(
        "expected che in romanize(チェ), but was " + actual, actual.contains(new CharsRef("che")));
  }
}
Command
# in a copy of this finding's repro folder (repro/LFV-850/, which holds src/)
# Lucene checkout at the tested commit, built with: ./gradlew --no-daemon assemble   (JDK 25)
LUCENE=/path/to/lucene; V=12.0.0-SNAPSHOT
CP=$LUCENE/lucene/core/build/libs/lucene-core-$V.jar
CP=$CP:$LUCENE/lucene/codecs/build/libs/lucene-codecs-$V.jar
CP=$CP:$LUCENE/lucene/test-framework/build/libs/lucene-test-framework-$V.jar
CP=$CP:$LUCENE/lucene/analysis/common/build/libs/lucene-analysis-common-$V.jar
CP=$CP:$LUCENE/lucene/analysis/kuromoji/build/libs/lucene-analysis-kuromoji-$V.jar
CP=$CP:randomizedtesting-runner-2.9.2.jar:junit-4.13.2.jar:hamcrest-3.0.jar   # test-framework dependencies (Maven Central)
CP=$CP:junit-platform-console-standalone-6.1.3.jar   # JUnit Platform console launcher (Maven Central)

javac -d classes -cp "$CP" $(find src -name '*.java')

# run 1: assertions on, seed DEADBEEF
java -ea -esa --add-modules jdk.incubator.vector --enable-native-access=ALL-UNNAMED -Dtests.seed=DEADBEEF \
     -cp "classes:$CP" org.junit.platform.console.ConsoleLauncher \
     execute --select-class org.apache.lucene.analysis.ja.completion.TestRomajiMapChe
# the module(s) analysis-kuromoji also need their third-party runtime jars
Expected vs actual
Expected: KatakanaRomanizer.romanize(チェ) contains che. Actual on main: [tixe, chixe], with -ea and -da.

All files of this repro: repro/LFV-850/

More files, environment, full output37 words

Environment

luceneLucene main e1faeba08bde (2026-11-02)
jdk25.0.3+9-LTS

Observed output

# Lucene main 645d4fe14a20, assertions on (-ea), seed DEADBEEF: 1 test(s) run, 1 failed
    => java.lang.AssertionError: expected che in romanize(チェ), but was [tixe, chixe]
       org.junit.Assert.fail(Assert.java:89)
       org.junit.Assert.assertTrue(Assert.java:42)
       org.apache.lucene.analysis.ja.completion.TestRomajiMapChe.testCheRomanizesToChe(TestRomajiMapChe.java:28)

Why it looks unintended

  • The javadoc lists "(modified) Hepburn-shiki": there チェ, イェ, ツァ are che, ye, tsa, as Lucene's reading-form romanizer also emits.
  • The table has シェ,sye,she, ティ,thi,texi, ウィ,wi, even ッイェ,yye, but no チェ, ディ, ウォ or イェ row.
  • The docs name one deviation (long vowels, as an example) and explain none of these gaps; in review, a missing jji was added on request.
The full argument474 words
  • The contract names modified Hepburn. JapaneseCompletionFilter.java:41-42 and romaji_map.txt:3 list "(modified) Hepburn-shiki" as supported. The module's Hepburn romanizer ToStringUtil maps チェ → che (:481), イェ → ye (:304) and ツァ/ツィ/ツェ/ツォ → tsa/tsi/tse/tso (:489-498), and TestToStringUtil asserts these (:154, :187-191). That romanizer has a different contract: it gives one modified-Hepburn reading per token for JapaneseReadingFormFilter (ToStringUtil.java:240, JapaneseReadingFormFilter.java:84-87), not a list of accepted keystrokes, so it corroborates the spellings but does not bind the completion table.
  • The disclaimer's example does not explain it. JapaneseCompletionFilter.java:44-48: "This does not strictly comply with the romanization systems listed above, but tries to cover possible keystroke supported by various Input Methods. e.g.: Circumflex / Macron representing Chōonpu (長音符) are not supported." Its one example of a deviation is the long-vowel mark; it is introduced with "e.g.", so it need not be the full list. che, ye, tsa, dhi, dhu and who are keystrokes the open-source Mozc romaji table accepts (it maps them to ちぇ, いぇ, つぁ, でぃ, でゅ, うぉ), so the stated aim of covering input-method keystrokes argues for them.
  • The table is inconsistent with itself. ッイェ,yye but no イェ; シェ, ジェ and チャ/チュ/チョ but no チェ; ティ/テュ but no ディ/デュ; ウィ/ウェ but no ウォ. It does have クァ, グァ, トゥ, ドゥ and ヴァ (:121-154), which the 1991 government notice on loanword spelling puts in its second, less common table, while its first table has チェ, ツァ/ツェ/ツォ, ディ and デュ (the intended-behaviour checker's reading of the notice).
  • The author's own reference has the rows. In #11140 the author named a comparison of romaji tables as a reference; its input-method loanword row lists sye she, zye je, tye che, tsa tsi tse tso, thi, thu, dhi, dhu, ye, who. Lucene's table has sye/she, zye/je, thi and thu but none of the others; nothing shows how the author picked entries from it (the intended-behaviour checker's reading of the page).
  • The same kind of gap was fixed on request. In the review of PR #297, a reviewer (GitHub johtani) asked on the ッジ,zzi row "Should we add jji? I usually use jajji for ジャッジ"; the author (GitHub mocobeta) answered "yes, of course" and added it.
  • Nothing pins the current spellings. No completion test covers these kana, no comment, CHANGES or MIGRATE entry mentions them, and an anchored exact-key git log --all -G search finds no commit that ever added or removed such a row.
  • Not proof of intent either way. No javadoc, test, CHANGES entry, commit message, saved PR text or code comment explains the absence of these rows; the points above support an undocumented omission, which maintainers may also label an alias-coverage improvement.
The devil's-advocate check215 words

The strongest case (the cross-model review and the intended-behaviour checker): the header says the table "does not strictly comply" and only "tries to cover" keystrokes, and every extended katakana already has some spelling through the small-vowel rows (chixe, ixe, tsuxa, dexi, uxo all work), so this is missing coverage, an enhancement, not a broken contract. ToStringUtil serves another contract, and every extra alias multiplies the indexed forms (a separate unbounded-expansion issue).

Why it is weaker than it looks: the one deviation the documentation names is the long-vowel mark (as an example, not a full list); the module's own Hepburn romanizer and its test use che, ye and tsa; the table covers the siblings and even the doubled ッイェ while missing イェ, which no coverage policy explains; and in the original review a spelling that a reviewer said they usually type (jji) was added as an omission. The best-effort wording, the separate ToStringUtil contract and the token cost lower the priority and may decide the label (bug or improvement); none of them shows that the gap was intended. Not claimed: Hepburn di, dyu, wo for ディ, デュ, ウォ, which this table already uses for ヂ, ヂュ and ヲ (:55, :60, :118).

Suggested fix

Recommended Add the 9 rows, keeping today's small-vowel spellings (recommended)

Add nine rows to romaji_map.txt that keep today's fallback spellings, for example チェ,tye,che,cye,tixe,chixe, イェ,ye,ixe, ツァ,tsa,tuxa,tsuxa, ディ,dhi,dexi, ウォ,who,uxo. The repro passes and all 198 kuromoji tests pass, assertions on and off. Existing suggest fields need reindexing.

All options and trade-offs4 options · 668 words

All options are edits of the bundled table only; no Java changes. The recommended option was validated in a scratch worktree at a9779ef3c193 with the whole :lucene:analysis:kuromoji:test task plus the paste-ready test, assertions on and off, and with the standalone runner on the end-to-end and reproducer tests. The row without the fallback spellings was run for チェ only (the finder's first sketch) and loses matches that work today.

Add the 9 rows, keeping today's small-vowel spellings (recommended) (validated by the checks)

Each row sits next to its siblings and follows the table's conventions: the y form first where the sibling rows have one (tye, built like チャ,tya; an input-method spelling the open-source Mozc table accepts, not shown to be an official Kunrei spelling), then the Hepburn and input-method forms, then the spellings the reading gets today (as クァ,kwa,kuxa and ヴォ,vo,vuxo keep them). A word's romaji after the fix are a superset of today's, so nothing that matches now stops matching.

 チュ,tyu,chu,cyu
+チェ,tye,che,cye,tixe,chixe
 チョ,tyo,cho,cyo
 ユ,yu
+イェ,ye,ixe
 ヨ,yo
 ヱ,we
+ウォ,who,uxo
 ヲ,wo,o
 スォ,swo,suxo
+ツァ,tsa,tuxa,tsuxa
+ツィ,tsi,tuxi,tsuxi
+ツェ,tse,tuxe,tsuxe
+ツォ,tso,tuxo,tsuxo
 テョ,tho,texyo
+ディ,dhi,dexi
+デュ,dhu,dexyu

Trade-offs

  • Every extra spelling multiplies a word's romaji tokens (the product in KatakanaRomanizer.java:138-156): チェ goes from 2 to 5 spellings, ツァ-ツォ from 2 to 3, the others from 1 to 2, so チェック goes from 2 romaji tokens to 5. That slightly enlarges a separate unbounded-expansion issue (different fix site); the module's random and huge-string tests still pass.
  • The ッ-prefixed forms (ッチェ, ッツァ, ...) still use the fallback; the table has no ッシェ or ッジェ row either, so adding them is a separate consistency step.
  • Existing suggest fields must be reindexed to gain the new tokens. The query side needs no code or configuration change (kana queries gain the new spellings too).

What the checks validated

  • Scratch worktree at a9779ef3c193, gradle, seed DEADBEEF: the paste-ready test fails 2 of 3 on stock main with assertions on and off; with this fix the whole :lucene:analysis:kuromoji:test task passes, 31 classes, 198 tests, 0 failures (7 skipped, all in pre-existing module tests: TestExtendedMode 1, TestFactories 1, TestJapaneseNumberFilter 2, TestJapaneseTokenizer 3), with assertions on and off. That includes the completion suites (TestJapaneseCompletionAnalyzer 4, TestJapaneseCompletionFilter 5, TestJapaneseCompletionFilterFactory 2, TestKatakanaRomanizer 2) and TestToStringUtil (3).
  • With the paste-ready test, ecjLintTest and checkGoogleJavaFormat pass.
  • The repro runner with the fixed table first on the class path: the paste-ready test passes (assertions on and off), the end-to-end suggester test passes (off), the independent reproducer's test passes 3 of 3 (on). A token probe shows ch, che, chekku, chixekku, y, ye, ts, tsa, dh, dhi, wh and who all completing their words.

The same rows without the small-vowel spellings (not suggested) (validated by the checks)

Like シェ,sye,she and ウィ,wi, which keep none, for example チェ,tye,che,cye (the finder's first sketch).

Trade-offs

Fewer tokens, but what matches today stops matching. Run for チェ only: chixekku no longer completes チェック, and neither does the composition state ちx (chi then x on the way to ちぇ), which completes it on stock main and with the recommended fix. The paste-ready test's control fails: "'chixekku' does not complete チェック [チェック, tyekku, chekku, cyekku]".

What the checks validated

Run as a negative check only: the paste-ready test fails its control with this チェ row, and the token probe loses chixekku and ちx.

Also add the ッ-prefixed forms (ッチェ, ッツァ-ッツォ, ッディ, ッデュ)

The finder's table-law check lists them as the next gap once the 9 rows exist.

Trade-offs

Consistency only; the table has no ッシェ or ッジェ row either. Untested.

Also add Hepburn di, dyu, wo to ディ, デュ, ウォ

Lucene's Hepburn romanizer gives di, dyu, wo for these kana.

Trade-offs

Not suggested without a maintainer's view: the table already uses them for ヂ (ヂ,di,zi,ji), ヂュ and ヲ (ヲ,wo,o), and the open-source Mozc table turns them into ぢ, ぢゅ and を, so a raw di would then complete both ヂ and ディ words. Untested.

Downstream note

Search servers that expose this filter as kuromoji_completion load the same table from the Lucene jar, so their Japanese autocomplete should miss the same spellings (inferred from the code; not run on those servers).

How it was found

A probe compared the romanizer with ICU4J's Katakana-Latin output for 132 hand-listed katakana units and flagged 23, among them チェ, イェ, ツァ-ツォ, ディ, デュ and ウォ. A model of the table's sibling rows located the gaps; a bounded-exhaustive check found KatakanaRomanizer matching an independent longest-match model on all 59 million tested inputs.

The method in full249 words
  • First signal. A planning probe compared the stock KatakanaRomanizer with the Latin spelling that ICU4J's Katakana-Latin transliterator gives (Hepburn che for チェ, but ie, uo and tsua for イェ, ウォ and ツァ) for a hand-listed chart of 132 gojūon, yōon and extended-katakana units, and flagged 23 units whose ICU spelling the romanizer does not produce, among them チェ, イェ, ウォ, ディ, デュ and ツァ-ツォ; an end-to-end probe showed chekku, disuku and wo suggesting nothing on the stock main jars.
  • Table laws. A model of the table's own regularities: law L4 (sibling-family closure) finds シェ/ジェ present but チェ absent, ウィ/ウェ but not ウォ, ッイェ but not イェ, no ツ+small-vowel row, and テァ-テョ without voiced デ rows.
  • Translation validation (bounded-exhaustive). Part A: romanize() equals an independent longest-match model of the table on all 1,830,854 inputs of length up to 3 and 57,289,761 inputs of length 4 (0 mismatches; a shortest-match mutant: 33,518 mismatches), so the defect is in the data. Part B: the Hepburn images of these extended katakana are missing (che, ye, tsa, ...; the colliding di, dyu, wo are not claimed). Part C: typing ye through a model input method (the open-source Mozc romaji table) already fails at the state y.
  • Reduction. A public-API JUnit with the document suggester on the stock main jars (2026-10-28), then this doc's kuromoji-only test.
  • Tier. Non-formal first signal: a check against another implementation's output; the table-law model and the bounded-exhaustive checks came after it.

Prior reports, history and checks

Prior reports

No matching prior report found in the sources searched (as of 2026-10-28) in GitHub issues, PRs and commits, JIRA, the mailing lists, open PRs' changed files, downstream projects and the web. Closest: the introducing PR #297, whose review added a missing jji spelling.

Searches4 searches

No report of this defect was found. The closest upstream text is the PR #297 review exchange about jji, a precedent for treating missing spellings as omissions, not a report of these rows. The table's data rows have not changed since 9.0.0 and no open PR changes them (the only open PR whose file list includes the table, #16911, deletes all of branch_10x).

What was searched, when, and what turned up
WhereWhenHowFound
GitHub issues, PRs and commits (apache/lucene), downstream repositories, mailing lists (dev@, java-user@, issues@, commits@), JIRA archive2026-10-28the scripted prior-report search, two runs (45 and 56 queries)one high-overlap hit, #11140 (the introduction); nothing about these rows
GitHub, by hand (apache/lucene, elastic/elasticsearch, opensearch-project/OpenSearch, apache/solr)2026-10-2825 issue and PR queries (romaji_map, ローマ字, チェ, ディ, LUCENE-10102, kuromoji completion, ...) and 4 code searches for copies of the table and the rows チェ,tye,che, ディ,dhi#11140, #297, #12047 (header typos), #11399 (offsets), #16416 and #12044 (refactors), #12885, #5499, #4988 (another romanizer); 17 code-search hits for the table file: the upstream file plus 16 copies in 13 other repositories (forks, ports and vendored checkouts); none adds the rows
Open and recent PRs2026-10-28the changed files of all 411 open apache/lucene PRs; the 60 PRs updated since 2026-10-26none changes romaji_map.txt or the completion package; the only one whose file list includes the table is #16911, which deletes all of branch_10x (not a fix)
Web (English and Japanese)2026-10-285 queries, 4 pages readusage articles and vendor documentation; none mentions these rows. The author's 2020 public version of the table has the same gap, undiscussed

History

In the table since it was added with the feature (4e86df96c03, #297, 2021-09-17; first released in 9.0.0); its data rows never changed. Fails on 9.0.0, 9.12.3, 10.0.0, 10.5.2, branch_10_6 and main; the other releases ship the same rows.

Versions tested6 rows

Introduced with the feature: 4e86df96c03 "LUCENE-10102: Add JapaneseCompletionFilter for Input Method-aware auto-completion (#297)", 2021-09-17 (issue #11140), which created romaji_map.txt; git blame on main assigns every sibling row and the fallback rows to it. The nine rows are absent from the PR's first draft dff3942 through the merged blob, and an anchored exact-key git log --all -G search finds no commit that ever added or removed one. The only later commit to the file on main and branch_10_6, 4676a735c18 (#12047, 2023-01-02), fixed two header-comment typos and added the final newline; branch_9x lists one more commit on the path, 4f358f76bc9 (2024-10-10, not examined), and the released 9.x tags keep the original blob.

Executed: the introducing commit (its completion classes and table on the 9.0.0 jars), 9.0.0, 9.12.3, 10.0.0, 10.5.2, the branch_10_6 head 4ae946e5a9b and main fail the same way; 8.11.4 has no completion filter. The table blob is 4a803a469ad in 9.0.0-9.12.3 and 8136668e708 in 10.0.0-10.5.2, branch_10_6 and main, with identical data rows (read). No fix upstream.

Versions and branches executed, with results
Version or commitVerdictResult
main a9779ef3c193 affectedpaste-ready test fails 2 of 3 (gradle and runner, assertions on and off); the end-to-end and reproducer tests fail
10.5.2, 9.12.3 affectedpaste-ready test fails with the same messages (published jars; 10.5.2 assertions on and off, 9.12.3 on)
9.0.0, 10.0.0, branch_10_6 4ae946e5a9b affectedend-to-end suggester test: the same six missing suggestions (9.0.0 and branch_10_6 assertions on and off)
4e86df96c03 (introducing commit) introits completion classes and table on the 9.0.0 jars: the same failure
8.11.4 no APIno completion filter: the test fails to compile only on JapaneseCompletionAnalyzer / JapaneseCompletionFilter
main + the 9-row fix not affectedthe paste-ready, end-to-end and reproducer tests pass; the whole kuromoji test task passes (198 tests)

Independent checks

The finder, an independent reproducer, an intended-behaviour checker, the adjudication and a credibility audit all ran code and said real. A reviewer from another model family (OpenAI GPT-5.6) could not run code and called it an enhancement while agreeing on the root cause. This doc's gradle runs confirm the repro and the fix.

Checks and verdicts333 words

Every verdict except the cross-model review's rests on executed runs on main a9779ef3c193. The cross-model review read the checkout at ea57360912ed, where the table is identical.

Each independent check and its verdict
CheckVerdictWhat it found
finder candidateTable-law model (law L4), bounded-exhaustive check of the real romanizer (Parts A-C); the end-to-end JUnit fails on main with assertions on and off and on 10.5.2. Its first fix sketch dropped tixe/chixe (found by the checks below).
independent reproducer real, LowOwn test through PrefixQuery and KatakanaRomanizer: 2 of 3 fail on main (on and off), 10.5.2 and 9.12.3; controls, including composed kana, pass; its 9-row table passes and keeps 11 upstream completion tests passing; found the fix-sketch regression.
refute review (OpenAI GPT-5.6) not real, medium (reading only)Could not run any command; it votes not real on a claim it could not reproduce, and it read the table as a best-effort alias list (an enhancement). It agreed on the root cause and that the inputs are legal. A separate test (an AnalyzingSuggester JUnit) reproduced the failure on main and 10.5.2.
intended-behaviour checker real, LowBuilt the best-effort case and rejected it (only the long-vowel deviation is documented; the module's Hepburn romanizer gives che/ye/tsa; ッイェ but no イェ; the jji precedent); re-ran on main and 10.5.2; probed dh, wh, y (fail) and ch, ts (work).
adjudication confirmed, medium; silent wrong results, LowRe-ran the finder's test (assertions on) and the reproducer's (off) with a fresh seed: both fail.
credibility audit keepRe-ran the finder's test on main with a new seed: the same six missing suggestions; re-read the table and re-checked prior art.
this doc reproduces; fix validatedGradle in a scratch worktree: the paste-ready test fails 2 of 3 on stock main with assertions on and off; the 9-row fix passes the whole kuromoji test task, 198 tests, on and off; the runner reproduces on 10.5.2 and 9.12.3.

Diagram file

The diagram as a still image, generated with AI and checked against the code. It is under 10 MB, the limit for a GitHub attachment.

Sources and provenance

Finding record, Lucene and upstream sources, repro files and diagram notes1,517 words

Finding record

LFV-850, snapshot of 2026-11-06

Registry title
Kuromoji's completion table romaji_map.txt has no rows for チェ, イェ, ツァ/ツィ/ツェ/ツォ, ディ/デュ and ウォ, although it has rows for their siblings (チャ/チュ/チョ, シェ/ジェ, ッイェ, ティ/テュ, ウィ/ウェ), so raw-romaji prefixes such as 'che', 'ye' and 'tsa' suggest nothing for words like チェック, イェール and ツァー
Area
analysis / kuromoji (JapaneseCompletionFilter and JapaneseCompletionAnalyzer romanization data: the bundled table romaji_map.txt that KatakanaRomanizer reads)
Priority
Low, rank 507: The opt-in completion table has no rows for loanword kana such as チェ, イェ, ツァ, ディ and ウォ, so those suggestions are lost silently but only when the loanwords are typed in raw romaji, which puts it with the Kuromoji romanization rare-input rows right after LFV-605.
Impact class
silent wrong results
Impact note
Applications that use the kuromoji JapaneseCompletionAnalyzer or JapaneseCompletionFilter for Japanese auto-completion (an opt-in module analyzer; default constructors, INDEX and QUERY mode) silently get no suggestion when a user types the usual raw-romaji spelling of a loanword with チェ, イェ, ツァ/ツィ/ツェ/ツォ, ディ, デュ or ウォ (chekku for チェック, ye for イェール, tsa for ツァー, and the IME keystrokes dhi, dhu and who), because these kana are indexed only through the small-vowel fallback (tixekku/chixekku, ixe, tuxa/tsuxa, dexi, dexyu, uxo), while queries composed in kana, even partly (ちぇっk), and the small-vowel spellings still match; no scale is needed, nothing fails or throws, and every release from 9.0.0 to 10.5.2, branch_10_6 (10.6.0) and main are affected.
Summary
You index ordinary loanwords such as チェック, イェール, ツァー, ディスク or ウォッカ with JapaneseCompletionAnalyzer and expect a user who types the usual romaji, che(kku), ye or tsa (or the IME keystrokes dhi, dhu, who), to get them as suggestions, because the analyzer lists (modified) Hepburn, Kunrei-shiki and Wapuro romanization as supported and its table already has these spellings for the sibling kana: シェ she, ジェ je, チャ cha, ティ thi, テュ thu, ウィ wi, ウェ we and even the doubled form ッイェ yye. Instead romaji_map.txt has no row for チェ, イェ, ツァ, ツィ, ツェ, ツォ, ディ, デュ or ウォ, so KatakanaRomanizer splits each into its base kana plus a small vowel (チ+ェ -> tixe/chixe, イ+ェ -> ixe, ツ+ァ -> tuxa/tsuxa, デ+ィ -> dexi, ウ+ォ -> uxo) and these raw-romaji queries suggest nothing. Queries typed in kana, including partly composed ones such as ちぇっk, still match, because the index and query sides use the same fallback.
Introduced
4e86df96c0385a7b552434d7e2a9bee69f18bd77 (apache/lucene#297, 'LUCENE-10102: Add JapaneseCompletionFilter for Input Method-aware auto-completion', issue #11140, by GitHub mocobeta, co-authored by rmuir; reviewers johtani and rmuir) [read: the commit added romaji_map.txt, KatakanaRomanizer, JapaneseCompletionFilter and JapaneseCompletionAnalyzer as new files; git blame on main puts every sibling row (シェ line 35, ジェ 44, チャ-チョ 51-53, ウィ 114, ウェ 116, テァ-テョ 155-160, ッイェ 251) and the small-vowel fallback rows (314-318) on it; git log -S finds no commit that ever added or removed a row keyed チェ, ディ, デュ, ウォ or ツァ-ツォ; the rows are absent from the first draft of the table in PR #297 (dff3942) through the merged blob; the only later commit on the file, 4676a735c18 (#12047), fixes header-comment typos] [exec: the commit's completion classes and table, shadowed on the 9.0.0 jars, fail the same way]. Present since the table was written, so not a regression; the table author's 2020 precursor table (a public gist) already had the same gap (2021-09-17 (author date 2021-09-17T13:37:12Z; merged 2021-09-17T13:37:13Z))
First affected version
9.0.0 [exec, -ea and -da] (the first release with JapaneseCompletionFilter; CHANGES lists LUCENE-10102 under 9.0.0 New Features; 8.11.4 [exec]: the repro does not compile, because the API is absent)
Affected versions
every release from 9.0.0 to 10.5.2 (33 releases), 10.6.0 (the branch_10_6 head 4ae946e5a9b) and main [exec: the finder's JUnit fails 1 of 1 with the same 6 typed strings on the introducing commit 4e86df96c03 (shadowed on the 9.0.0 jars, -ea), 9.0.0 (-ea and -da), 9.12.3 (-ea), 10.0.0 (-ea), 10.5.2 (-ea and -da), the branch_10_6 head 4ae946e5a9b (10.6.0, released 2026-10-29; kuromoji compiled from the branch sources; -ea and -da) and main a9779ef3c193 (-ea and -da); the independent reproduction's JUnit fails on main, 10.5.2 and 9.12.3; a separate AnalyzingSuggester JUnit fails on main and 10.5.2; the intended-behaviour check reproduced on main and 10.5.2; the finder's portable main() sweep fails on 9.0.0, 9.12.3, 10.5.2 and main] [read: the other releases ship the same table data: blob 4a803a469ad in 9.0.0-9.12.3 and 8136668e708 in 10.0.0-10.5.2, branch_10_6 and main, whose data rows are identical, and git tag --contains 4e86df96c03 lists them all; upstream main head 20ced71c1e6 has the same blob]; not applicable to 8.x and older (API absent [exec: 8.11.4]). All runs: JDK 25.0.3, Linux aarch64, release jars SHA-1 checked
Status
documented (brief, checks and a per-finding doc exist)
Verification
Confirmed by AI-run checks: an independent repro, a cross-model review that could only read the code (its “not real” is procedural), an intended-behaviour check, a prior-report search and a skeptical audit; not yet triaged by a person.
Found by
non-formal; also reached by exhaustive check
Upstream and prior reports
none found (2026-10-28, the prior-report record verdict new, read-only; 135 queries and 4 page fetches plus history and file scans): two scripted prior-report searches (45 and 56 queries) over apache/lucene issues and PRs, commits, downstream repositories (Elasticsearch, OpenSearch, Solr), the dev@, java-user@, issues@ and commits@ lists and the JIRA archive; 25 manual GitHub issue and PR searches over apache/lucene, elastic/elasticsearch, opensearch-project/OpenSearch and apache/solr (one rate-limited and retried); 4 GitHub code searches (17 copies of romaji_map.txt in forks and ports, none adds the rows); the commit history of the table and the completion package on main and branch_10_6; the changed files of all 411 open apache/lucene PRs (kuromoji files only in #16272, #12517, #12295 and #681, none in ja/completion; #16911 deletes branch_10x wholesale) and the 60 PRs updated since 2026-10-26; 5 web searches in English and Japanese and 4 pages fetched; 17 items read in full. The finder's, the independent reproduction's, the intended-behaviour check's (32 queries) and the adjudication's searches found nothing either. Re-check 2026-10-28: no apache/lucene issue or PR updated since 2026-10-27 concerns kuromoji or romaji; the searches 'romaji' and 'JapaneseCompletionFilter' return only the known #12885, #10164, #4988, #11399, #16416, #11140 and #297; no kuromoji item was created since 2026-10-26; the table's commits on main and branch_10_6 are still only 4e86df96c03 and 4676a735c18; upstream main head 20ced71c1e6, branch_10_6 head 4ae946e5a9b. Context, not reports: #11140 / #297 (the introduction, with the 'jji' review request), #12047 (comment typos), #16416 (output buffering), #11399 / LUCENE-10363 (offsets), the table author's 2020 gist precursor with the same gap, and a byte-identical Rust port of the table. Gaps: GitHub search is token-based and CJK queries depend on its tokenizer, private reports to the security list are invisible, and searches cannot prove absence)
Lucene commit tested
main a9779ef3c193 (gradle in a scratch worktree, assertions on and off, and the standalone JUnit runner); the release jars 10.5.2 (assertions on and off) and 9.12.3 (this doc's paste-ready test); 9.0.0, 9.12.3, 10.0.0, 10.5.2, the branch_10_6 head 4ae946e5a9b and the introducing commit 4e86df96c03 on the 9.0.0 jars (the history step, end-to-end suggester test); the 9-row table fix on main (gradle, whole kuromoji test task, assertions on and off).

Lucene and upstream sources

Finding record
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:1-5 (header: 'covers romanization systems: modified Hepburn-shiki, Kunrei-shiki (Nihon-shiki), and Wapuro shiki' and 'does not strictly comply ... but tries to cover possible keystroke supported by various Input Methods'), :35 シェ,sye,she, :44 ジェ,zye,je, :47 チ,ti,chi, :48 ツ,tu,tsu, :51-53 チャ/チュ/チョ, :57 デ,de, :114 ウィ,wi, :116 ウェ,we, :121 クァ,kwa,kuxa, :156 ティ,thi,texi, :159 テュ,thu,texyu, :251 ッイェ,yye, :314-318 ァ..ォ -> xa..xo; no row keyed チェ, イェ, ウォ, ディ, デュ, ツァ, ツィ, ツェ or ツォ (grep, 2026-10-28)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilter.java:36-58 (class javadoc: supported systems; 'does not strictly comply'; the only documented deviation is Circumflex / Macron for the long vowel mark)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/completion/KatakanaRomanizer.java:99-120 (romanize: greedy longest keystroke match over the table)
The finding in 30 seconds
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:3-5 (at a9779ef3c193) (header), :8, :9, :35, :44, :47, :48, :51-53, :57, :114, :116, :156, :159, :251, :314-318; no row keyed チェ, イェ, ツァ, ツィ, ツェ, ツォ, ディ, デュ or ウォ (grep)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilter.java:41-48 (at a9779ef3c193) (javadoc), :217-233 (generateOutputs)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/completion/KatakanaRomanizer.java:44-84 (at a9779ef3c193) (table load), :103-169 (romanize)
Who is affected
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionAnalyzer.java:36-54 (at a9779ef3c193) (default constructor, INDEX/QUERY, analysis chain)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilterFactory.java:38 (at a9779ef3c193) (SPI name japaneseCompletion)
Why it looks unintended
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilter.java:41-48 (at a9779ef3c193)
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:3-5, (at a9779ef3c193) :35, :44, :51-53, :55, :60, :114, :116, :118, :121-154, :156, :159, :251
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/dict/ToStringUtil.java:240 (at a9779ef3c193) ("Romanize katakana with modified hepburn"), :304, :329, :481, :489-498, :942, :945
  • lucene/analysis/kuromoji/src/test/org/apache/lucene/analysis/ja/dict/TestToStringUtil.java:154, (at a9779ef3c193) :159, :187-191, :196, :198
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseReadingFormFilter.java:84-87 (at a9779ef3c193) (the reading-form filter calls ToStringUtil.getRomanization)
  • lucene/analysis/kuromoji/src/test/org/apache/lucene/analysis/ja/completion/TestKatakanaRomanizer.java:26-56 (at a9779ef3c193) (the inputs it covers)
Suggested fix
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/completion/KatakanaRomanizer.java:108-115 (at a9779ef3c193) (longest match), :138-156 (Cartesian product)
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:55, (at a9779ef3c193) :60, :118, :121, :154 (ヂ, ヂュ, ヲ, クァ, ヴォ)
  • lucene/analysis/kuromoji/src/test/org/apache/lucene/analysis/ja/completion/TestKatakanaRomanizer.java:43-45 (at a9779ef3c193) (ヴォルテール keeps vuxo)

Other statements trace to the hunt's working files (models, logs, reviews and briefs), which are not published.

Repro files

About the diagrams

The PNG is the summary card. Made in parallel with this doc.

Built 2026-11-06 from the hunt's record of this finding and its doc file. Lucene main under test in this hunt: ea57360912ed. Every listed finding was re-run on Lucene main e1faeba08bde on 2026-11-02.