All findings · Lucene finding · LFV-849 · romaji-map-sokuon-rows-miss-doubled-spellings

Kuromoji completion: a small tsu before shi, chi or tsu gets no doubled Hepburn spelling, so typing `zasshi` never suggests 雑誌

With JapaneseCompletionAnalyzer, typing zasshi, macchi or mittsu suggests nothing for 雑誌, マッチ or 三つ, while issho finds 一緒: the bundled table romaji_map.txt gives ッシ, ッチ and ッツ only ssi, tti and ttu. Every release since 9.0.0.

Summary

Priority
Medium, rank 147Common words such as 雑誌, 決して, マッチ and 三つ silently get no suggestion in the opt-in kuromoji completion analyzer for their usual Hepburn spellings, and that broad trigger on everyday words puts it in Medium at the end of the opt-in silent analysis rows, while its sibling completion-table rows LFV-850, LFV-848 and LFV-854 stay Low.
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; 33 releases to 10.5.2 and 10.6.0 run
Status
documented
Found by
table self-consistency check and a bounded-exhaustive check of the romanizer

AI-assisted page: this finding was first signalled by a semi-formal check (an exact check of the real jar, or a modelling hypothesis that a tool then witnessed) 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 row by row from the bundled table romaji_map.txt, so a suggester can match Latin-letter input.

Summary card of the bug. Panel 1: the application indexes 雑誌 with JapaneseCompletionAnalyzer and queries 'zasshi' with PrefixCompletionQuery, expecting [雑誌]; the javadoc lists modified Hepburn as supported. Panel 2: 雑誌 has the reading ザッシ, split by longest match into ザ za and ッシ ssi, so the index-side tokens are 雑誌 and zassi; typed 'zasshi' and indexed 'zassi' differ at the 5th letter, so the suggester returns nothing. Panel 3: romaji_map.txt doubles the consonant on its neighbouring small-tsu rows but has only ssi, tti and ttu for ッシ, ッチ and ッツ. Panel 4: zasshi, kesshite, macchi, mittsu, matcha and the composition ざっsh find nothing on main; the Kunrei spellings, issho, maccha and committed kana still match; the data-only fix makes all of them found.
Summary card: what the application does, how 雑誌 is indexed (ザ + ッシ gives only zassi), why zasshi is not a prefix of it, the table rows that miss the doubled spelling, and the executed result. Select the still to open it at full size. Generated with AI, checked against the code.
  1. You index 雑誌 (zasshi), 決して (kesshite), マッチ (macchi) and 三つ (mittsu) as suggestions with JapaneseCompletionAnalyzer, plus 一緒 (issho) and 抹茶 (maccha), and query with PrefixCompletionQuery.
  2. You expect zasshi to suggest 雑誌, as issho suggests 一緒: the javadoc lists modified Hepburn, and doubling the consonant is how input methods type a small tsu.
  3. Instead all four return no suggestion, with no error. Of the Latin spellings tried, only the Kunrei ones work (zassi finds 雑誌, mittu finds 三つ); committed kana work too.
  4. Why: 雑誌 is indexed as [雑誌, zassi]. Its table row ッシ,ssi has one spelling, while シ,si,shi has two and the neighbour ッショ,ssyo,ssho doubles sh. ッチ (tti) and ッツ (ttu) are the same.
  5. Input-method users lose it while composing: ざっs (zass) finds 雑誌, ざっsh (zassh) finds nothing, the committed ざっし finds it again.

Who is affected

Applications using the opt-in JapaneseCompletionAnalyzer or JapaneseCompletionFilter (also exposed by search servers as kuromoji_completion), with the standard INDEX/QUERY configuration, in every release since 9.0.0. Familiar words, for example 雑誌, 決して, マッチ, 三つ, こっち, 抹茶 (how often such words occur was not measured). People typing raw romaji lose the suggestion; input-method users lose it while composing. Committed kana still match.

Mechanism, terms and numbers580 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 gives the small-tsu rows ッシ, ッチ and ッツ a single Kunrei-style spelling (ssi, tti, ttu), although the base rows list shi, chi, tsu and the neighbouring small-tsu rows double the consonant (ssha, ccha, jji). So 雑誌, 決して, マッチ and 三つ are indexed only as zassi, kessite, matti and mittu, and typing the modified-Hepburn or input-method spellings zasshi, kesshite, macchi or mittsu suggests nothing, with no error. It affects every release from 9.0.0 to 10.6.0 and main; the fix is data only.

Terms

  • Small tsu (sokuon, ッ / っ): doubles the next consonant. 雑誌 is read ザッシ, za-sshi.
  • Romanizations: modified Hepburn writes シ, チ, ツ as shi, chi, tsu and a small tsu before them as sshi, tchi, ttsu (雑誌 zasshi, 三つ mittsu, 抹茶 matcha); Kunrei-shiki writes si, ti, tu (zassi, mittu). Japanese input methods accept both and type a small tsu by doubling the consonant (ss, cc, tt) or with tch; macchi is such an input-method spelling.
  • JapaneseCompletionFilter: for each word it emits the word itself and every romaji spelling of its katakana reading at the same position. The spellings come from romaji_map.txt, where each row maps a key, mostly a kana unit, to its spellings (for example シ,si,shi); the reading is matched longest key first, and every spelling of every matched row is combined (KatakanaRomanizer.java:103-169). The javadoc lists "(modified) Hepburn-shiki, Kunrei-shiki (Nihon-shiki) and Wāpuro shiki" as supported (JapaneseCompletionFilter.java:41-42).
  • Completion query: PrefixCompletionQuery matches a suggestion when the typed text, after the QUERY-mode analyzer, is a prefix of one of the suggestion's indexed forms. Raw romaji such as zasshi comes out as the single token zasshi; no romaji token is added.

The bug

rowspellingsbase rowneighbouring rows
:185 ッシssi:29 シ,si,shi:189-191 ッシャ,ssya,ssha / ッシュ,ssyu,sshu / ッショ,ssyo,ssho
:201 ッチtti:47 チ,ti,chi:205-207 ッチャ,ttya,ccha,ccya (and ッチュ, ッチョ)
:202 ッツttu:48 ツ,tu,tsu:193 ッジ,zzi,jji, :218 ッフ,hhu,ffu

Smaller gaps of the same kind: ッチャ, ッチュ, ッチョ have no Hepburn tch form (matcha), and the rare ッヂ, ッヅ, ッヂャ, ッヂュ, ッヂョ rows (:209-210, :213-215) have no zz/jj form.

The numbers

Index-side tokens on main: 雑誌 → [雑誌, zassi], 決して → [決して, kessite], マッチ → [マッチ, matti], 三つ → [三つ, mittu], こっち → [こっち, kotti]; compare 一緒 → [一緒, issyo, issho] and 抹茶 → [抹茶, mattya, maccha, maccya]. Typed zasshi, kesshite, macchi, matchi, mittsu, matcha: no suggestion, and kocchi is not a prefix of any token of こっち. Typed zassi, kessite, issho, maccha: found. Lucene's Hepburn reading filter (JapaneseReadingFormFilter, useRomaji=true) gives zasshi, kesshite, matchi, mittsu, matcha for the same words.

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 omission itself is in the data rows.

Exposure and likelihood223 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 standard INDEX/QUERY configuration, no user dictionary and no custom table.
  • What triggers it. Ordinary words whose reading has ッシ, ッチ or ッツ, typed in modified Hepburn or the way input methods type them: 雑誌 zasshi, 決して kesshite, マッチ macchi / matchi, 三つ mittsu, こっち kocchi, and 抹茶 matcha (the tch gap). No special input, no scale.
  • Two groups of users. People who type romaji directly lose the suggestion completely. Input-method users lose it between the small tsu and the completed kana (ざっsh → zassh, みっts → mitts); handling such mid-composition strings is a stated goal of the feature (JapaneseCompletionFilter.java:184-188).
  • What still works. Kana committed through an input method (ざっし → zassi) and the Kunrei spellings (zassi, mittu).
  • 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 code or configuration change; QUERY mode loads the same table, so kana queries gain the new spellings too (with fix C, ざっし → [ざっし, zassi, zasshi]).

Minimal repro

The test shows that the INDEX-mode JapaneseCompletionAnalyzer gives 雑誌 (ザッシ) only the Kunrei romaji zassi, never the modified-Hepburn zasshi (romaji_map.txt maps ッシ only to ssi), so typing "zasshi" cannot complete it.

TestCompletionSokuonHepburn.java (JUnit test)44 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;

import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.tests.util.LuceneTestCase;

public class TestCompletionSokuonHepburn extends LuceneTestCase {

  public void testZasshiIsIndexed() throws Exception {
    List<String> terms = new ArrayList<>();
    try (Analyzer analyzer =
            new JapaneseCompletionAnalyzer(null, JapaneseCompletionFilter.Mode.INDEX);
        TokenStream ts = analyzer.tokenStream("f", "雑誌")) {
      CharTermAttribute term = ts.addAttribute(CharTermAttribute.class);
      ts.reset();
      while (ts.incrementToken()) {
        terms.add(term.toString());
      }
      ts.end();
    }
    // expected: the Hepburn spelling "zasshi" among the index-side tokens; actual: [雑誌, zassi]
    assertTrue(
        "expected zasshi among the index-side tokens, actual: " + terms, terms.contains("zasshi"));
  }
}
Command
# in a copy of this finding's repro folder (repro/LFV-849/, 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.TestCompletionSokuonHepburn
# the module(s) analysis-kuromoji also need their third-party runtime jars
Expected vs actual
Expected zasshi among the index-side tokens; actual [雑誌, zassi], with -ea and -da.

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

More files, environment, full output38 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 zasshi among the index-side tokens, actual: [雑誌, zassi]
       org.junit.Assert.fail(Assert.java:89)
       org.junit.Assert.assertTrue(Assert.java:42)
       org.apache.lucene.analysis.ja.TestCompletionSokuonHepburn.testZasshiIsIndexed(TestCompletionSokuonHepburn.java:41)

Why it looks unintended

  • The javadoc lists "(modified) Hepburn-shiki" as supported; zasshi, mittsu and matcha are Hepburn, and Lucene's own Hepburn reading filter emits them.
  • The same table doubles sh, ch, j and f on the neighbouring small-tsu rows (ッショ,ssyo,ssho, ッチャ,ttya,ccha,ccya, ッジ,zzi,jji).
  • In the introducing PR's review, the same kind of gap (no jji on ッジ) was fixed on request: "yes, of course".
The full argument349 words
  • The contract names modified Hepburn. JapaneseCompletionFilter.java:41-42 and romaji_map.txt:3 list "(modified) Hepburn-shiki" as supported. zasshi, kesshite, mittsu and matcha are the modified-Hepburn forms, and JapaneseReadingFormFilter with useRomaji=true emits them.
  • The feature exists to cover more than Hepburn. The introducing issue #11140 says JapaneseReadingFormFilter "supports only modified Hepburn-shiki, so it isn't sufficient to cover all possible romanized forms". For these words the completion filter covers fewer forms than that filter.
  • 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." Doubled consonants (ss, cc, tt) and tch are ordinary input-method keystrokes for a small tsu (the open-source Mozc input method maps each to っ), so the disclaimer's stated aim argues for them. Its example ("e.g.") of what is not supported is long-vowel marks; no comment, test or doc names the small-tsu rows. The first wording, replaced a day later by 5dfbef313cf (before 9.0.0), excluded "romanji forms which are official but not commonly used with Japanese Input Methods".
  • The neighbouring rows follow the rule. The table doubles sh, ch, j and f on the neighbouring small-tsu rows (:189-191, :193, :205-207, :218); the base rows シ, チ, ツ list two spellings each. (It is not consistent everywhere: a sibling bug covers two copy errors on other small-tsu rows, :281 ッスォ and :289 ッドゥ.)
  • The same 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 jji, jja, jju, jjo (PR commit fc90e452474), whose diff shows ッチ,tti and ッツ,ttu as unchanged context.
  • Nothing pins the current spellings. No upstream test covers a small tsu before シ, チ or ツ (they cover サッカ, ヒャッカテン, コダッk and サッk), and no comment, CHANGES or MIGRATE entry mentions it.
The devil's-advocate check130 words

The strongest case (the cross-model review and the intended-behaviour checker): the table is a curated, best-effort set ("does not strictly comply"), every extra spelling multiplies the completion paths (the expansion behind a separate registry bug), and the document-suggester classes are @lucene.experimental.

Why it fails: the table gives two to four spellings to 123 of its 329 rows and to 56 of the 158 rows whose key starts with ッ (ッファ, ッフィ, ッフェ, ッフォ list four), so bounding the product cannot explain dropping exactly these rows; the review that added jji treated the same gap as an omission; and the defect is in the tokens of the kuromoji filter, which is not marked experimental and feeds any suggester. What remains is a labelling question (bug fix or improvement), not intent.

Suggested fix

Recommended The doubled spellings on all 11 small-tsu rows that lack them (broadest)

The broadest of three data-only options: add the doubled spellings to romaji_map.txt: ッシ,ssi,sshi, ッチ,tti,cchi,tchi, ッツ,ttu,ttsu, plus tch on ッチャ/ッチュ/ッチョ and zz/jj on the ッヂ/ッヅ rows (11 rows). The repro passes and all 196 kuromoji tests pass, assertions on and off. Existing suggest fields need reindexing.

-ッシ,ssi
+ッシ,ssi,sshi
-ッチ,tti
-ッツ,ttu
+ッチ,tti,cchi,tchi
+ッツ,ttu,ttsu
-ッチャ,ttya,ccha,ccya
+ッチャ,ttya,ccha,ccya,tcha
   (ッチュ, ッチョ: + tchu, tcho)
-ッヂ,ddi,
-ッヅ,ddu
+ッヂ,ddi,zzi,jji
+ッヅ,ddu,zzu
   (ッヂャ, ッヂュ, ッヂョ: + zzya,jja / zzyu,jju / zzyo,jjo)
All options and trade-offs3 options · 598 words

All options are edits of the bundled table only; no Java changes. Fix C and fix A were validated in a scratch worktree at a9779ef3c193 with the whole :lucene:analysis:kuromoji:test task plus the paste-ready test; fix A also with assertions off in the independent fact check; fix B was validated by the independent reproducer with the standalone runner. A fixes the four headline misses, B adds the Hepburn tch forms, C also adds the rare ッヂ/ッヅ rows for consistency, which are the least supported part. None touches the separate copy-error rows :281 ッスォ and :289 ッドゥ.

The doubled spellings on all 11 small-tsu rows that lack them (broadest) (validated by the checks) (recommended)

Each affected row gets its base row's spellings with the first consonant doubled (sh → ssh, ch → cch, ts → tts, z/j → zz/jj), plus the Hepburn tch form on ッチ, ッチャ, ッチュ and ッチョ.

-ッシ,ssi
+ッシ,ssi,sshi
-ッチ,tti
-ッツ,ttu
+ッチ,tti,cchi,tchi
+ッツ,ttu,ttsu
-ッチャ,ttya,ccha,ccya
+ッチャ,ttya,ccha,ccya,tcha
   (ッチュ, ッチョ: + tchu, tcho)
-ッヂ,ddi,
-ッヅ,ddu
+ッヂ,ddi,zzi,jji
+ッヅ,ddu,zzu
   (ッヂャ, ッヂュ, ッヂョ: + zzya,jja / zzyu,jju / zzyo,jjo)

Trade-offs

  • Every extra spelling multiplies a word's romaji tokens: each ッシ, ッツ or ッヅ in a reading doubles the count, each ッチ, ッヂ, ッヂャ, ッヂュ or ッヂョ triples it, and ッチャ/ッチュ/ッチョ go from 3 to 4 spellings. マッチ goes from [matti] to [matti, macchi, matchi]. That slightly enlarges a separate unbounded-expansion issue (different fix site); the module's random and huge-string tests still pass.
  • The ッヂ/ッヅ part (5 rows) concerns rare kana and is not directly asserted by any test run. For it: the table's own closure check flags these rows, and the finder's standards check finds their Hepburn and Kunrei images missing. Against it: in the saved input-method table the new zzi/jji compose to っじ (not っぢ), zzu to っず (not っづ), and the yōon forms likewise to ジ forms, although the base rows already alias ヂ with ジ and ヅ with ズ. Keep it for consistency, not as a headline, or drop it (the 6-row option).
  • 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 on stock main with assertions on and off; with this fix the whole :lucene:analysis:kuromoji:test task passes, 31 classes, 196 tests, 0 failures (7 skipped, all in pre-existing module tests: TestExtendedMode 1, TestFactories 1, TestJapaneseNumberFilter 2, TestJapaneseTokenizer 3; no stock whole-module run to compare), with assertions on and off.
  • 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 and the end-to-end suggester test pass; earlier, the 13 upstream completion tests passed with the combined table of all four sibling table fixes under 4 seeds, all with assertions on.

Only the three headline rows (minimal) (validated by the checks)

ッシ,ssi,sshi, ッチ,tti,cchi,tchi, ッツ,ttu,ttsu (+3/-3).

Trade-offs

Smallest change; leaves matcha and the ッヂ/ッヅ rows as they are.

What the checks validated

The whole kuromoji test task: 31 classes, 196 tests, 0 failures, with assertions on (this doc) and off (the independent fact check); the end-to-end test passes too.

The three rows plus tch on ッチャ/ッチュ/ッチョ (6 rows) (validated by the checks)

Adds matcha-style Hepburn spellings, without the rare ッヂ/ッヅ rows.

Trade-offs

Middle ground between the two options above.

What the checks validated

By the independent reproducer only, with the standalone runner: its 4 tests pass with this table.

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

Semi-formal. A self-consistency check of the table (every ッK row should list K's spellings with the first consonant doubled) and a Hepburn standards check flagged these rows; a bounded-exhaustive check showed KatakanaRomanizer implements the table as written (0 mismatches on 59 million inputs). A public-API JUnit then reproduced the missing suggestions.

The method in full219 words
  • First signal. A planning probe checked romaji_map.txt against its own small-tsu rule and flagged ッシ, ッチ, ッツ and the ッヂ/ッヅ rows; its end-to-end probe showed zasshi, kesshite, macchi and mittsu returning no suggestion on the stock main jars.
  • Table laws. A model of the table's rules: the gemination-closure law found 10 violations, 8 of them this bug's rows (the other 2 belong to a sibling copy-error bug).
  • 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); the Part A counters completed, then that process ran out of memory entering Part B, so Parts B and C ran separately. Part B: the modified-Hepburn, Kunrei and Nihon-shiki images of every sequence of up to 4 kana units, from an independent standards table, isolate the failing small-tsu units. Part C: typing the words through a model input method (the open-source Mozc romaji table) finds the failing composition states っsh, っts and tc.
  • 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. Semi-formal: the first signal came from a table self-consistency script, not from a solver's or model checker's own output.

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 and recent PRs' changed files, downstream projects and the web. Closest: the introducing PR #297, whose review added a missing jji on ッジ.

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 such gaps as omissions, not a report of these rows. The table's data rows have not changed since 9.0.0 and no open PR touches the file.

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 archive, web2026-10-28the scripted prior-report search, 51 queries, plus a 28-query lists and JIRA variant (24 list and 4 JIRA queries, 283 hits, triaged)run 1: no high hit, 7 medium (#11140, #297, #16416 and web documentation pages); the variant: one high hit, LUCENE-10102 (#11140, the introduction), the rest low; nothing about these rows
GitHub, by hand (apache/lucene, downstream projects and all of GitHub)2026-10-2816 queries on apache/lucene (romaji, Hepburn, kuromoji completion, sokuon, ッシ, 促音, ローマ字, gemination, kunrei, wapuro, ...) and 12 downstream and global queries (JapaneseCompletionFilter, KatakanaRomanizer, romaji_map.txt)#11140, #297, #12047 (header typos), #11399 (offsets), #16416 (refactor), #12044, #12885 (a different class); downstream documentation and exposure items only
Open and recent PRs2026-10-28the changed files of all 411 open apache/lucene PRs and of the 150 PRs closed 2026-09-04 to 2026-10-28; PRs updated since 2026-10-26none touches romaji_map.txt, KatakanaRomanizer or JapaneseCompletionFilter (#16911 deletes all of branch_10x; not a fix)
Web (English and Japanese)2026-10-28romaji_map.txt, zasshi, sshi/ttsu, sokuon, 促音 サジェスト, ヘボン式 っしvendor documentation and how-to posts; none mentions these rows. The author's 2020 public version of the table has the same rows, 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 all 33 releases from 9.0.0 to 10.5.2, on 10.6.0 (branch_10_6 4ae946e5a9b) and on main.

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 affected row to it. The PR's first commit dff3942eed5 (2021-09-13) already had ッシ,ssi, ッチ,tti, ッツ,ttu; the review commit fc90e452474 added jji to the ッジ rows and left ッシ, ッチ and ッツ unchanged. The only later commit to the file, 4676a735c18 (#12047, 2023-01-02), fixed header comments.

Executed: all 33 releases from 9.0.0 to 10.5.2 (21 in 9.x, 12 in 10.x) and the branch_10_6 head 4ae946e5a9b (assertions on), and main (on and off), fail the same way; a fixed table on the classpath turns 9.0.0 and 10.5.2 into passes. 8.11.x has no completion filter. Upstream main 20ced71c1e6 and branch_10x carry the same table (read only). No fix upstream.

Versions and branches executed, with results
Version or commitVerdictResult
main a9779ef3c193 affectedpaste-ready test fails (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 message (published jars, assertions on)
9.0.0 to 10.5.2 (33 releases), branch_10_6 4ae946e5a9b affectedend-to-end suggester test, assertions on: the same four missing suggestions in every release
8.11.0, 8.11.4 no APIno completion filter: the test fails to compile only on JapaneseCompletionAnalyzer / JapaneseCompletionFilter
9.0.0, 10.5.2 + fixed table not affectedthe end-to-end test passes
main + fix C, main + fix A not affectedthe paste-ready test passes; the whole kuromoji test task passes (196 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; on reading it agreed with the root cause. This doc's gradle runs confirm the repro and both validated fixes.

Checks and verdicts369 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 (10 gemination-closure violations), bounded-exhaustive check of the real romanizer (Parts A-C); the end-to-end JUnit fails on main with assertions on and off, 10.5.2 and 9.0.0; the fixed table passes.
independent reproducer realOwn public-API test: 3 of 4 fail on main (assertions on and off), 10.5.2 (on and off) and 9.12.3; the Hepburn reading-filter control passes; its own table fix passes 4 of 4. Found the PR #297 jji review exchange.
intended-behaviour checker real, highRejected the best-effort disclaimer, the 'query mode targets input methods only' reading and the 'bound the romaji product' reading; re-ran the test on main and 10.5.2: fails. Probed the composition states.
refute review (OpenAI GPT-5.6) not real, low (procedural)Could not run any command in four attempts, so it voted not real on procedure only; on reading it agrees with the root cause and writes that static review "strongly favors a genuine resource-table defect". It read Lucene head ea57360912ed, where the table and the completion classes are identical. A separate run re-ran the finder's test on 10.5.2 with assertions off: fails.
adjudication confirmed, high; silent wrong resultsRe-ran the reproducer's test on main with assertions on and off: 3 of 4 fail with the same messages.
credibility audit keepRe-ran the finder's test on main with assertions on and off: fails, controls pass; re-read the table rows and re-checked prior art.
this doc reproduces; fixes validatedGradle in a scratch worktree: the paste-ready test fails on stock main with assertions on and off; fix C (on and off) and fix A (on) pass the whole kuromoji test task, 196 tests.
fact checks of this doc holds after correctionsAn independent fact check re-ran the gradle repro (assertions on and off), fix A (off) and fix C (on and off), and a real-suggester probe; a reviewer from another model family (OpenAI GPT-5.6) re-checked the claims against the saved evidence. Their corrections are applied.

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,251 words

Finding record

LFV-849, snapshot of 2026-11-06

Registry title
Japanese completion suggester (JapaneseCompletionAnalyzer / JapaneseCompletionFilter): words with a small tsu before shi, chi or tsu (雑誌, 決して, マッチ, 三つ) are never suggested for their Hepburn or input-method spellings zasshi, kesshite, macchi/matchi, mittsu, because romaji_map.txt maps ッシ only to 'ssi', ッチ only to 'tti' and ッツ only to 'ttu', while the base rows シ/チ/ツ list shi/chi/tsu and the neighbouring rows ッシャ and ッチャ do double the consonant ('ssha', 'ccha')
Area
analysis / kuromoji completion romanization (romaji_map.txt read by KatakanaRomanizer; JapaneseCompletionFilter, JapaneseCompletionAnalyzer)
Priority
Medium, rank 147: Common words such as 雑誌, 決して, マッチ and 三つ silently get no suggestion in the opt-in kuromoji completion analyzer for their usual Hepburn spellings, and that broad trigger on everyday words puts it in Medium at the end of the opt-in silent analysis rows, while its sibling completion-table rows LFV-850, LFV-848 and LFV-854 stay Low.
Impact class
silent wrong results
Impact note
Applications that build Japanese autocomplete with JapaneseCompletionAnalyzer or JapaneseCompletionFilter (an opt-in kuromoji analyzer, used with its default settings; downstream search servers expose it as a kuromoji_completion filter), in every release from 9.0.0 to 10.6.0 and main: every word whose reading contains ッシ, ッチ or ッツ (雑誌, 決して, 必死, こっち, 一致, 三つ, 四つ) is indexed only with the Kunrei-style romaji (zassi, kessite, matti, mittu), so a query typed in raw romaji with the Hepburn or doubled-consonant spelling (zasshi, kesshite, macchi, matchi, mittsu, and matcha for 抹茶) gets no suggestion; kana committed through an input method still match, and input-method users lose the suggestion only while composing (ざっsh, みっts); no scale is needed and there is no error; a fix changes the index-side romaji tokens, so existing suggest fields would need reindexing to benefit.
Summary
You index 雑誌 ('magazine'), マッチ ('match') and 三つ ('three') in a document suggester with JapaneseCompletionAnalyzer, whose javadoc lists modified Hepburn among the supported romanizations, and expect typing 'zasshi', 'macchi' or 'mittsu' to suggest them, just as 'issho' suggests 一緒 and 'maccha' suggests 抹茶. Instead nothing is suggested: the bundled romaji_map.txt gives the small-tsu rows ッシ, ッチ and ッツ only the spellings 'ssi', 'tti' and 'ttu', although the base rows シ, チ, ツ list shi, chi, tsu and the neighbouring rows ッシャ and ッチャ list 'ssha' and 'ccha'. Only the Kunrei spellings (zassi, matti, mittu) find these words.
Introduced
4e86df96c0385a7b552434d7e2a9bee69f18bd77 (LUCENE-10102 / issue #11140, PR #297, 'Add JapaneseCompletionFilter for Input Method-aware auto-completion'): the commit created romaji_map.txt with the defective rows [read: git log --follow and git blame of romaji_map.txt on main]. Inside the PR, its first commit dff3942eed5 (2021-09-13) already had ッシ,ssi / ッチ,tti / ッツ,ttu, and PR commit fc90e452474 (2021-09-17) added jji/jja/jju/jjo to the ッジ rows after a review request while leaving these rows unchanged [read]. The only later commit to the file, 4676a735c18 (#12047, 2023-01-02), changed header comments only. (2021-09-17 (author and merge date of 4e86df96c03))
First affected version
9.0.0 [exec] (the first release with JapaneseCompletionFilter / romaji_map.txt; on 8.11.0 and 8.11.4 the repro fails to compile only because those classes are absent)
Affected versions
Every release from 9.0.0 to 10.5.2 (33 releases; latest 9.x: 9.12.3; latest 10.x before 10.6.0: 10.5.2), the branch_10_6 head 4ae946e5a9b9 (10.6.0, released 2026-10-29) and main a9779ef3c193 [exec: the same JUnit fails identically on each with -ea, main also with -da; a fixed romaji_map.txt on the classpath turns it into a pass on 9.0.0 and 10.5.2]. Upstream main 20ced71c1e6 and branch_10x carry the identical table blob [read]. The release jars ship two blobs of the file (4a803a469ad in 9.x, 8136668e708 in 10.x and main) with identical data rows [read]. No fix exists; no regression window and no last good version.
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 low-confidence “not real” is procedural), an intended-behaviour check, a prior-report search and a skeptical audit; not yet triaged by a person.
Found by
semi-formal; also reached by exhaustive check
Upstream and prior reports
none found (2026-10-28, read-only; the prior-report record, verdict new: a scripted prior-report search with 51 queries over apache/lucene issues, PRs and commits, downstream repositories, the dev@, java-user@, issues@ and commits@ lists, the JIRA archive and the web, a 283-hit lists and JIRA variant, manual GitHub searches, the changed files of 411 open PRs and of the PRs closed since 2026-09-04, and the review threads of #297, #11140 and #12047; a later re-check: no apache/lucene PR or issue updated since 2026-10-26 concerns kuromoji or romaji, and no open PR #16805-#16926 touches kuromoji files; its keyword searches hit the search rate limit and rest on the earlier runs): no issue, PR, JIRA entry, list thread or downstream report says that ッシ, ッチ or ッツ lack the sshi, cchi/tchi or ttsu spellings, or that zasshi or mittsu get no suggestion. Related, different: #11140 / #297 (the introduction; in #297's review a reviewer, GitHub johtani, asked to add jji to ッジ and the author agreed: a precedent, not a report of these rows), #12047 (header typos), #11399 (JapaneseCompletionFilter offsets, open), #16416 (ArrayDeque refactor of the filter), #12885 (JapaneseReadingFormFilter OOV hiragana), #16911 (decommissions branch_10x, which removes the file there; not a fix), elastic/elasticsearch#117807 and opensearch-project/OpenSearch#4835 (downstream docs and exposure only).
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 and 9.12.3 (this doc's paste-ready test); all 33 releases from 9.0.0 to 10.5.2 and the branch_10_6 head 4ae946e5a9b (the history step, end-to-end suggester test); fix A and fix C tables on main (gradle, whole kuromoji test task).

Lucene and upstream sources

Finding record
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:3-5 (at a9779ef3c193) (header: 'covers romanization systems: modified Hepburn-shiki, Kunrei-shiki (Nihon-shiki), and Wāpuro shiki'; 'does not strictly comply ... but tries to cover possible keystroke supported by various Input Methods')
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:29 (at a9779ef3c193) (シ,si,shi), :47 (チ,ti,chi), :48 (ツ,tu,tsu)
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:185 (at a9779ef3c193) (ッシ,ssi), :189-191 (ッシャ,ssya,ssha / ッシュ,ssyu,sshu / ッショ,ssyo,ssho), :193 (ッジ,zzi,jji), :201 (ッチ,tti), :202 (ッツ,ttu), :205-207 (ッチャ,ttya,ccha,ccya ... no tch), :209-215 (ッヂ,ddi, / ッヅ,ddu / ッヂャ,ddya ...), :218 (ッフ,hhu,ffu)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilter.java:41-42 (at a9779ef3c193) ('Supported romanization systems: (modified) Hepburn-shiki, Kunrei-shiki (Nihon-shiki) and Wāpuro shiki'), :44-48 (disclaimer naming only circumflex/macron long vowels as unsupported), :217-233 (generateOutputs: index-side tokens are the surface form plus KatakanaRomanizer.romanize of the reading)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/completion/KatakanaRomanizer.java:103-169 (at a9779ef3c193) (romanize: greedy longest match over the table rows, Cartesian product of the matched row's spellings)
The finding in 30 seconds
  • lucene/analysis/kuromoji/src/resources/org/apache/lucene/analysis/ja/completion/romaji_map.txt:3-5 (at a9779ef3c193) (header), :29, :47, :48, :185, :189-191, :193, :201, :202, :205-207, :209-210, :213-215, :218
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilter.java:41-48 (at a9779ef3c193) (javadoc), :180-193 (mid-composition), :217-233 (generateOutputs)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/completion/KatakanaRomanizer.java:52-65 (at a9779ef3c193) (table load), :103-169 (romanize)
Who is affected
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionAnalyzer.java:42-59 (at a9779ef3c193) (INDEX/QUERY constructor, analysis chain)
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/JapaneseCompletionFilter.java:184-188 (at a9779ef3c193) (mid-IME composition comment)
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) :29, :47, :48, :189-191, :193, :205-207, :218
  • lucene/analysis/kuromoji/src/test/org/apache/lucene/analysis/ja/TestJapaneseCompletionFilter.java:215-216; (at a9779ef3c193) completion/TestKatakanaRomanizer.java:39-52
  • lucene/suggest/src/java/org/apache/lucene/search/suggest/document/CompletionAnalyzer.java:35, (at a9779ef3c193) SuggestField.java:48, PrefixCompletionQuery.java:39 (@lucene.experimental)
  • row counts: a parse of romaji_map.txt at a9779ef3c193 with the loader's rules (329 rows, 123 with 2-4 spellings; 158 rows whose key starts with ッ (157 without the bare row ッ,xtu), 56 with 2-4)
Suggested fix
  • lucene/analysis/kuromoji/src/java/org/apache/lucene/analysis/ja/completion/KatakanaRomanizer.java:138-156 (at a9779ef3c193) (Cartesian product)

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.