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.
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.- You index チェック, イェール and ツァー as suggestions with
JapaneseCompletionAnalyzer, plus the control シェア, and query withPrefixCompletionQuery. - You expect
chekkuto suggest チェック, assheasuggests シェア: the javadoc lists modified Hepburn, where チェ ische, イェyeand ツァtsa, and the open-source Mozc input-method table accepts the same keystrokes. - Instead
chekku,yeandtsareturn no suggestion, with no error. So do the input-method keystrokesdhisuku(ディスク),dhuetto(デュエット) andwhokka(ウォッカ). - Why: the table has
シェ,sye,sheand evenッイェ,yye, but no row for チェ or イェ. So チェ is split into チ (ti,chi) plus a small ェ (xe), and チェック becomes[チェック, tixekku, chixekku];cheis a prefix of neither. - 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,wandwh(two keystrokes before うぉ), orty/cyif they type ちぇ astye/cye.
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.
- 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 mapsdhi,dhu,whoto でぃ, でゅ, うぉ; a small vowel alone can be typed withx(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 fromromaji_map.txt, where each row maps a key to its spellings (for exampleシェ,sye,she);KatakanaRomanizermatches 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:
PrefixCompletionQuerysuggests 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 aschekkucomes out as the single tokenchekku.
| kana | row today | spellings produced (fallback) | sibling rows that exist |
|---|---|---|---|
| チェ | none | tixe, chixe (:47 チ,ti,chi + :317 ェ,xe) | :35 シェ,sye,she, :44 ジェ,zye,je, :51-53 チャ / チュ / チョ |
| イェ | none | ixe (:8 イ,i + ェ) | :251 ッイェ,yye (the doubled form) |
| ツァ, ツィ, ツェ, ツォ | none | tuxa, tsuxa ... (:48 ツ,tu,tsu + :314-318) | none for ツ |
| ディ, デュ | none | dexi, dexyu (:57 デ,de + small vowel) | :156 ティ,thi,texi, :159 テュ,thu,texyu |
| ウォ | none | uxo (:9 ウ,u + :318 ォ,xo) | :114 ウィ,wi, :116 ウェ,we |
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
JapaneseCompletionAnalyzerorJapaneseCompletionFilter(also through the analysis SPI asjapaneseCompletion; search servers built on Lucene expose it as akuromoji_completiontoken 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 でぃ/でゅ),wand thenwh(before うぉ, two keystrokes), andty/cyif they type ちぇ astye/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]).
The test shows that Kuromoji's romaji_map.txt has no row for チェ (it has シェ and チャ), so チェ gets only the small-vowel fallback romaji.
/*
* 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")));
}
}
# 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.
More files, environment, full output37 words
| lucene | Lucene main e1faeba08bde (2026-11-02) |
|---|---|
| jdk | 25.0.3+9-LTS |
# 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)- 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
jjiwas added on request.
The full argument474 words
- The contract names modified Hepburn.
JapaneseCompletionFilter.java:41-42andromaji_map.txt:3list "(modified) Hepburn-shiki" as supported. The module's Hepburn romanizerToStringUtilmaps チェ →che(:481), イェ →ye(:304) and ツァ/ツィ/ツェ/ツォ →tsa/tsi/tse/tso(:489-498), andTestToStringUtilasserts these (:154,:187-191). That romanizer has a different contract: it gives one modified-Hepburn reading per token forJapaneseReadingFormFilter(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,dhuandwhoare 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.
ッイェ,yyebut 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 hassye/she,zye/je,thiandthubut 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
ッジ,zzirow "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 -Gsearch 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).
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.
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,dexyuTrade-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:testtask 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,
ecjLintTestandcheckGoogleJavaFormatpass. - 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,whandwhoall completing their words.
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.
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.
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.
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).
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
KatakanaRomanizerwith the Latin spelling that ICU4J's Katakana-Latin transliterator gives (Hepburnchefor チェ, butie,uoandtsuafor イェ, ウォ 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 showedchekku,disukuandwosuggesting 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 collidingdi,dyu,woare not claimed). Part C: typingyethrough a model input method (the open-source Mozc romaji table) already fails at the statey. - 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.
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).
| Where | When | How | Found |
|---|---|---|---|
| GitHub issues, PRs and commits (apache/lucene), downstream repositories, mailing lists (dev@, java-user@, issues@, commits@), JIRA archive | 2026-10-28 | the 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-28 | 25 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 PRs | 2026-10-28 | the changed files of all 411 open apache/lucene PRs; the 60 PRs updated since 2026-10-26 | none 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-28 | 5 queries, 4 pages read | usage articles and vendor documentation; none mentions these rows. The author's 2020 public version of the table has the same gap, undiscussed |
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.
| Version or commit | Verdict | Result |
|---|---|---|
main a9779ef3c193 | affected | paste-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 | affected | paste-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 | affected | end-to-end suggester test: the same six missing suggestions (9.0.0 and branch_10_6 assertions on and off) |
4e86df96c03 (introducing commit) | intro | its completion classes and table on the 9.0.0 jars: the same failure |
| 8.11.4 | no API | no completion filter: the test fails to compile only on JapaneseCompletionAnalyzer / JapaneseCompletionFilter |
| main + the 9-row fix | not affected | the paste-ready, end-to-end and reproducer tests pass; the whole kuromoji test task passes (198 tests) |
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.
| Check | Verdict | What it found |
|---|---|---|
| finder | candidate | Table-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, Low | Own 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, Low | Built 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, Low | Re-ran the finder's test (assertions on) and the reproducer's (off) with a fresh seed: both fail. |
| credibility audit | keep | Re-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 validated | Gradle 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. |
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.
- PNG 504 KB
Finding record, Lucene and upstream sources, repro files and diagram notes1,517 words
- 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 head4ae946e5a9band the introducing commit4e86df96c03on 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).
- 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, :251lucene/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, :945lucene/analysis/kuromoji/src/test/org/apache/lucene/analysis/ja/dict/TestToStringUtil.java:154, (at a9779ef3c193) :159, :187-191, :196, :198lucene/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)
- TestRomajiMapChe.java (JUnit test):
repro/LFV-850/src/org/apache/lucene/analysis/ja/completion/TestRomajiMapChe.java(31 lines)
The PNG is the summary card. Made in parallel with this doc.
assets/LFV-850/bug.png(504 KB)
![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.](../assets/LFV-850/bug.png)