All findings · Lucene finding · LFV-728 · smartcn-unicode-space-separators-not-skipped

SmartChineseAnalyzer indexes THIN SPACE, EM SPACE, FORM FEED and 11 other whitespace characters as one-character terms

SmartChineseAnalyzer skips only five space characters, so THIN SPACE, EM SPACE, FORM FEED and 11 other Unicode whitespace characters each become a one-character term: hello<U+2009>world is indexed as [hello, U+2009, world] and the exact phrase "hello world" misses it. In every release since 2.9.0 (2009).

Summary

Priority
Medium, rank 146The stock SmartChineseAnalyzer indexes 14 rare Unicode spaces as terms, which breaks phrases that cross one of them, a rare-input relevance error.
Impact
silent wrong results
Since
2.9.0 (2009, LUCENE-1629, the original contribution)introduced 2009-05-14 · over 17 years
Affected
every release from 2.9.0 through 10.6.0, and main
Status
documented
Found by
exhaustive character-class sweep over the BMP (semi-formal)

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

Before it finds words, SmartChineseAnalyzer gives every character a class. SPACE_LIKE characters are skipped; OTHER characters become one-character terms. Fourteen whitespace characters land in OTHER.

Background in three steps

  1. SmartChineseAnalyzer (module analysis-smartcn) splits Chinese text into words with a dictionary, and keeps runs of Latin letters or digits together as one term.
  2. First Utility.getCharType gives each character a class: Chinese character, letter, digit, punctuation (DELIMITER), SPACE_LIKE ("Characters that act as a space"), full-width letter or digit, or OTHER.
  3. The segmenter skips SPACE_LIKE characters and joins Chinese characters across them; punctuation becomes a token that the default stop list removes; each OTHER character becomes a term of its own.
Diagram of the bug: the inputs hello world and hello followed by a THIN SPACE (U+2009) and world go through SmartChineseAnalyzer. getCharType puts the ordinary space in SPACE_LIKE, which is skipped, giving the terms hello and world; it puts the THIN SPACE in OTHER, which becomes a one-character term, giving hello, U+2009, world, so the exact phrase hello world no longer matches.
hello world and hello<U+2009>world through SmartChineseAnalyzer: the space is skipped, the THIN SPACE becomes a term of its own. Select the still to open it at full size. Generated with AI, checked against the code.

The finding, step by step

  1. Analyze hello world and hello<U+2009>world (a THIN SPACE between the words) with the stock new SmartChineseAnalyzer().
  2. You expect [hello, world] for both: the segmenter has a class for "Characters that act as a space" and skips them, as it does a space, a tab or the ideographic space U+3000.
  3. The second gives [hello, U+2009, world]. Only five characters are in that class; THIN SPACE falls into "Other" and becomes a term of its own. The same holds for VERTICAL TAB, FORM FEED, OGHAM SPACE MARK and all of U+2000-U+200A: 14 characters.
  4. Search changes with it: the exact phrase "hello world" matches 3 of 7 documents that differ only in the separator, a TermQuery for U+2003 alone finds its document, and 中<U+2009>国 gives [中, U+2009, 国] where 中 国 gives [中国].
  5. No error. HTML does the same when an application puts Lucene's HTMLStripCharFilter in front of the analyzer: &emsp;&emsp; adds two U+2003 terms (&nbsp; decodes to a plain space and is fine).

Who is affected

Users of the optional smartcn module (SmartChineseAnalyzer with any constructor, or HMMChineseTokenizer) whose text contains one of the 14 characters, literally or via &emsp;, &ensp; or &thinsp; in HTML. Usually it only adds a term; results go wrong when a phrase or Chinese word spans the character, or a query targets it. Rare and silent; a fix needs reindexing.

Mechanism, terms and numbers655 words

SmartChineseAnalyzer's segmenter has a character class for "Characters that act as a space" (CharType.SPACE_LIKE), which it skips, but Utility.getCharType puts only space, tab, CR, LF and U+3000 in it. VERTICAL TAB, FORM FEED, OGHAM SPACE MARK and the eleven spaces U+2000-U+200A (EN QUAD to HAIR SPACE, among them EN, EM and THIN SPACE) fall through to OTHER, and every OTHER character is emitted as a one-character term that the default stop list does not remove. So hello<U+2009>world is indexed as [hello, U+2009, world], an exact phrase typed with a normal space misses it, a TermQuery for the space character alone finds it, and 中<U+2009>国 is no longer segmented as the word 中国. Nothing throws. It has been there since the original contribution (2.9.0, 2009) and is still on main.

The mechanism (main 5adff78bb168)

  1. The class table. Utility.getCharType (Utility.java:140-159) returns SPACE_LIKE only for ' ', '\t', '\r', '\n' and U+3000 (:146-147). The "Punctuation Marks" ranges come next: 0x0021-0x00BB, 0x2010-0x2642, 0x3001-0x301E (:148-151), then full-width letters and digits and 0xFE30-0xFF63 (:153-157). U+000B and U+000C lie below 0x0021, U+1680 is in no range, and U+2000-U+200A lie just below 0x2010, so all 14 reach return CharType.OTHER (:158).
  2. What the classes mean. CharType.SPACE_LIKE: "Characters that act as a space" (CharType.java:38-39); CharType.OTHER: "Other (not fitting any of the other categories)" (:47-48).
  3. The segmenter. HHMMSegmenter.createSegGraph skips SPACE_LIKE characters (HHMMSegmenter.java:56-58) and steps over them while it extends a Chinese word (:92), which is why 中 国 becomes 中国. Any other class ends the word. The default branch, which OTHER reaches, makes a one-character WordType.STRING token ("Treat the unrecognized char symbol as unknown string. For example, any symbol not in GB2312 is treated as one of these.", :156-165).
  4. The term text. WordSegmenter.convertSegToken copies the original character back into a STRING token (WordSegmenter.java:69-75), so the term is the whitespace character itself.
  5. No stop entry. SmartChineseAnalyzer.createComponents chains HMMChineseTokenizer, PorterStemFilter and a StopFilter with the default stop set (SmartChineseAnalyzer.java:124-135). That set "is simply a list of punctuation" (:103-104); it lists U+3000 with the comment "Used as a space in Chinese" (stopwords.txt:54-55) and none of the 14 characters, so the term is indexed.
  6. Why exactly 14. Lucene's pinned Unicode 17 White_Space set (UnicodeProps.WHITESPACE, UnicodeProps.java:33-40) has 25 code points: 5 are SPACE_LIKE; U+0085, U+00A0, U+2028, U+2029, U+202F and U+205F fall into the DELIMITER ranges and are removed like a comma; the other 14 fall through to OTHER.

The 14 characters

U+000B VERTICAL TAB, U+000C FORM FEED, U+1680 OGHAM SPACE MARK, U+2000 EN QUAD, U+2001 EM QUAD, U+2002 EN SPACE, U+2003 EM SPACE, U+2004 THREE-PER-EM SPACE, U+2005 FOUR-PER-EM SPACE, U+2006 SIX-PER-EM SPACE, U+2007 FIGURE SPACE, U+2008 PUNCTUATION SPACE, U+2009 THIN SPACE, U+200A HAIR SPACE.

The numbers (main 5adff78bb168, default SmartChineseAnalyzer())

inputterms (position increment)expected
hello world, hello<TAB>world, hello<U+3000>world[hello/1, world/1]the same
hello<U+2009>world, and the same for each of the 14[hello/1, U+2009/1, world/1][hello/1, world/1]
中 国[中国/1]the same
中<U+2009>国, and the same for each of the 14[中/1, U+2009/1, 国/1][中国/1]
exact phrase "hello world" over 7 documents that differ only in the separator (space, tab, U+3000, FF, U+1680, U+2003, U+2009)3 hits7 hits
TermQuery for U+000C, U+2003 or U+2009 alonefinds its documentfinds nothing
<p>&emsp;&emsp;我购买了道具和服装。</p> through HTMLStripCharFilter[U+2003, U+2003, 我, 购买, 了, 道具, 和, 服装]the words only

Not claimed: the no-break spaces U+00A0 and U+202F, U+205F MEDIUM MATHEMATICAL SPACE, and U+0085, U+2028, U+2029 are removed exactly like a comma (hello<U+00A0>world gives [hello/1, world/2], as hello,world does). That position gap after removed punctuation is tested design (TestSmartChineseAnalyzer.java:119-128), and Lucene has no single rule for no-break spaces. (The third no-break space, U+2007 FIGURE SPACE, is one of the 14.)

Exposure and likelihood403 words
  • Who is hit. Users of the optional analysis-smartcn module: SmartChineseAnalyzer with any constructor, or HMMChineseTokenizer / the hmmChinese factory with the SmartChinese stop list. Default settings, any scale. Only text that contains one of the 14 characters, in documents or queries.
  • What goes wrong. (1) A whitespace-only term is indexed, and a TermQuery for that character finds the document. (2) An exact phrase typed with an ordinary space misses words on both sides of the character; slop 1 still matches, because the extra term takes one position. (3) Chinese characters are no longer joined into a word across it: 中<U+2009>国 is indexed as 中, U+2009, 国, so the term 中国 is not indexed for that text. A FORM FEED inside a word splits it the same way (道<U+000C>具 gives 道, U+000C, 具, where a newline keeps 道具). (4) Each extra term also counts toward the field length that the norms store (IndexingChain.java:2055), so such a document's scores shift slightly (read from the code, not run).
  • How the characters arrive. As literal characters (typographic spacing, text extracted with form feeds), or through HTML when an application puts Lucene's HTMLStripCharFilter in front of the analyzer (it is not part of the stock SmartChineseAnalyzer): the char filter decodes &emsp;, &ensp; and &thinsp; to U+2003, U+2002 and U+2009, so an &emsp;&emsp; paragraph indent adds two U+2003 terms. &nbsp; decodes to U+0020 and is not a trigger.
  • Silent. Nothing throws, the index stays valid, and assertions on or off behave the same.
  • Likelihood: rare. Most occurrences, such as a paragraph indent, only add an extra term; a wrong match needs a query that spans the character (an exact phrase across it, or a Chinese word split by it) or a query for the character itself. No report in the 17 years since 2.9.0.
  • Not affected. Space, tab, CR, LF and U+3000 are skipped as intended. StandardAnalyzer, CJKAnalyzer and WhitespaceAnalyzer emit no whitespace-only term for the same inputs.
  • After a fix. Indexed terms change for text with these characters, so affected fields need reindexing.
  • Workaround today (from the code, not run): map these characters to U+0020 with a char filter (for example a MappingCharFilter) in front of HMMChineseTokenizer in a custom analyzer. A custom stop set that lists the 14 characters removes the terms too, but, like fix D, it leaves a position gap and does not join Chinese characters across them.

Minimal repro

One JUnit test, one method, public API: the default SmartChineseAnalyzer() on hello<U+2009>world. It fails on main and on the 10.6.0, 10.5.2, 9.12.3 and 9.1.0 jars, with assertions on and off, and in 20 of 20 iterations.

TestSmartChineseThinSpace.java (one test method)30 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.cn.smart;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.tests.analysis.BaseTokenStreamTestCase;

public class TestSmartChineseThinSpace extends BaseTokenStreamTestCase {

  public void testThinSpaceIsSkippedLikeASpace() throws Exception {
    try (Analyzer analyzer = new SmartChineseAnalyzer()) {
      // "hello world" gives [hello, world]; THIN SPACE (U+2009) should act as a space too
      assertAnalyzesTo(analyzer, "hello\u2009world", new String[] {"hello", "world"});
    }
  }
}
Command
cd $LUCENE
cp $REPRO/TestSmartChineseThinSpace.java lucene/analysis/smartcn/src/test/org/apache/lucene/analysis/cn/smart/
./gradlew :lucene:analysis:smartcn:test --tests org.apache.lucene.analysis.cn.smart.TestSmartChineseThinSpace -Ptests.seed=DEADBEEF -Ptests.asserts=true
# assertions off fails the same way: -Ptests.asserts=false
Expected
hello<U+2009>world analyzes to [hello, world], like hello world.
Observed
It analyzes to [hello, U+2009, world]: term 1 expected:<[world]> but was:<[ ]>.

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

More files, environment, full output217 words

The test sits in org.apache.lucene.analysis.cn.smart like the module's own tests but uses only public API. One 11-character input, the default constructor (so the default stop list), single thread, deterministic. The source is plain ASCII: the THIN SPACE is written as a Java Unicode escape. It compiles from 9.1.0 on (org.apache.lucene.tests). For a release, compile and run the same file against that release's lucene-core, lucene-analysis-common, lucene-analysis-smartcn and lucene-test-framework jars.

Pass -Ptests.asserts explicitly: on current main its default is drawn from the seed and the module path ("Run with assertions for ~75% of all seeds"), and seed DEADBEEF turns assertions off for this module.

The [ ] in the failure message is the THIN SPACE term. The same test is the suggested regression test; it passes with the recommended fix.

Environment

lucenemain 5adff78bb168 (12.0.0-SNAPSHOT), 10.6.0, 10.5.2, 9.12.3, 9.1.0: fail
jdkOpenJDK 25.0.3 (build 25.0.3+9-LTS)
osLinux, aarch64

Observed output

# gradle, main 5adff78bb168, seed DEADBEEF, -Ptests.asserts=true
TestSmartChineseThinSpace > testThinSpaceIsSkippedLikeASpace FAILED
    org.junit.ComparisonFailure: term 1 expected:<[world]> but was:<[ ]>
        at org.apache.lucene.tests.analysis.BaseTokenStreamTestCase.assertTokenStreamContents(BaseTokenStreamTestCase.java:262)
        ...
        at org.apache.lucene.analysis.cn.smart.TestSmartChineseThinSpace.testThinSpaceIsSkippedLikeASpace(TestSmartChineseThinSpace.java:27)

# the same failure: gradle with -Ptests.asserts=false; the JUnit runner on main (-ea and -da), 10.6.0 (-ea and -da), 10.5.2, 9.12.3 and 9.1.0
# main, 20 iterations (seed 5C0C2009): 20 of 20 fail
# main with the recommended fix: passes (assertions on and off)

Why it looks unintended

  • CharType.SPACE_LIKE is documented as "Characters that act as a space"; THIN SPACE and FORM FEED act as spaces, yet land in OTHER.
  • The stop-list design points the same way: the stop list even lists the already-skipped U+3000, "Used as a space in Chinese".
  • Lucene fixed an earlier getCharType misclassification as a bug (LUCENE-8325, 7.4.0).
The full argument314 words

This is the case for calling it a bug. It is medium confidence: no public contract promises how Unicode whitespace is handled, and maintainers may reasonably treat the change as an enhancement (see the devil's advocate below).

  • Contract. CharType.SPACE_LIKE is "Characters that act as a space" and OTHER is "Other (not fitting any of the other categories)" (CharType.java:38-39, :47-48). THIN SPACE, EM SPACE and FORM FEED act as spaces, so OTHER contradicts the documented meaning of both classes.
  • The stop-list design points the same way. The default stop list lists U+3000 "Used as a space in Chinese" (stopwords.txt:54-55) although U+3000 is already skipped (perhaps only redundancy, but it fits an intent to keep spaces out of the index); HMMChineseTokenizerFactory says the tokenizer "will currently emit tokens for punctuation" and tells users to remove them, for example with the SmartChinese stop list (:27-30); and in #3089 (LUCENE-2014, 2009) rmuir described smartcn as creating "individual tokens for each piece of punctuation (including things like whitespace)" and putting "these in the stopword list". None of the 14 characters is in that list.
  • The list was meant to be open. Utility.SPACES reads "Space-like characters that need to be skipped: such as space, tab, newline, carriage return." (Utility.java:41-44); the original Chinese javadoc in e01aad89fe2 ends in "等等" ("etc."), and the original CharType comment says "space, \t\r\n and other space or line-break characters".
  • Not a GB2312 rule. VT and FF are ASCII and encodable in GB2312, yet they are not SPACE_LIKE and become terms.
  • Other Lucene analyzers tried do not do this. StandardAnalyzer, CJKAnalyzer and WhitespaceAnalyzer emit no whitespace-only term for the same inputs.
  • Precedent. #9372 (LUCENE-8325, fixed in 7.4.0) fixed an earlier getCharType misclassification (surrogates turned into bad one-character tokens) as a bug.
  • Nothing pins it. No upstream test, CHANGES or MIGRATE entry asserts or mentions a whitespace term.
The devil's-advocate check194 words

The strongest case for "intended" came from an independent reviewer from another model family (OpenAI GPT-5.6, refute lens), which reproduced the behaviour, agreed on the cause and the fix, and still called the change an enhancement: Utility.SPACES lists exactly five characters; HHMMSegmenter says "any symbol not in GB2312" becomes an unknown-string token; testNonChinese says other text is split per character "(regardless of Unicode category)" (TestSmartChineseAnalyzer.java:182-185); the classes are @lucene.experimental; and where Lucene promises Unicode whitespace splitting it says so (UnicodeWhitespaceTokenizer).

Why it fails: Utility.SPACES has no reader on main (its last one, SentenceTokenizer, was removed in 6.0.0 by LUCENE-5969) and introduces its examples with "such as"; the GB2312 comment explains the fallback for unrecognized characters, not why VT and FF are unrecognized; testNonChinese is about letters of other writing systems (it asserts Arabic letters), not separators; the claim is "do not index whitespace as a term", not "split like UnicodeWhitespaceTokenizer"; and @lucene.experimental did not stop LUCENE-8325 from being fixed as a bug. What is left is that the contract is descriptive, not a sentence saying "whitespace is never indexed"; that is why the confirmation is medium confidence.

Suggested fix

Recommended A. Treat the remaining Unicode whitespace as SPACE_LIKE at the OTHER fall-through (validated)

Just before return CharType.OTHER in Utility.getCharType, return SPACE_LIKE for UnicodeProps.WHITESPACE, Lucene's pinned White_Space set: +3 lines, and only the 14 characters change. The repro passes with assertions on and off, and so do the smartcn module's 22 tests and its static checks. Indexed terms change, so affected fields need reindexing.

import org.apache.lucene.analysis.util.UnicodeProps;
...
    if (ch >= 0xFE30 && ch <= 0xFF63) return CharType.DELIMITER;
    // Other Unicode whitespace (VT, FF, U+1680, U+2000-U+200A) also acts as a space
    if (UnicodeProps.WHITESPACE.get(ch)) return CharType.SPACE_LIKE;
    return CharType.OTHER;
All options and trade-offs4 options · 566 words

Four options. A was validated with gradle on main 5adff78bb168; B in standalone runs only; C was run by an earlier check and is incomplete; D was not run.

A. Treat the remaining Unicode whitespace as SPACE_LIKE at the OTHER fall-through (validated) (recommended)

UnicodeProps.WHITESPACE is Lucene's pinned Unicode 17 White_Space set. At the fall-through it can only catch characters no earlier branch classified, which are exactly the 14. The six White_Space characters in the DELIMITER ranges (U+0085, U+00A0, U+2028, U+2029, U+202F, U+205F) keep today's behaviour; U+2007 FIGURE SPACE, a no-break space, is one of the 14 and changes (see the trade-offs). smartcn already requires analysis-common (module-info.java:21, build.gradle:24).

import org.apache.lucene.analysis.util.UnicodeProps;
...
    if (ch >= 0xFE30 && ch <= 0xFF63) return CharType.DELIMITER;
    // Other Unicode whitespace (VT, FF, U+1680, U+2000-U+200A) also acts as a space
    if (UnicodeProps.WHITESPACE.get(ch)) return CharType.SPACE_LIKE;
    return CharType.OTHER;

Trade-offs

  • Changes indexed terms for text with these characters: reindex, and a CHANGES entry.
  • The set follows Lucene's pinned Unicode version, not the JDK's.
  • U+2007 FIGURE SPACE, a no-break space, becomes skipped like any space, so Chinese characters are joined across it (中<U+2007>国: [中/1, U+2007/1, 国/1] today, [中国/1] with the fix); the other no-break spaces, U+00A0 and U+202F, stay DELIMITER and still split, with a position gap (中<U+00A0>国 -> [中/1, 国/2] today and with the fix). In Latin text all three keep separating the words. Treating U+2007 like an ordinary space is a policy choice to flag for the maintainers.

What the checks validated

  • Gradle in a scratch worktree of 5adff78bb168 (the script reverts its changes and records an empty git status afterwards), OpenJDK 25.0.3, seed DEADBEEF: stock, the repro fails with assertions on and off; with the fix it passes with assertions on and off.
  • The whole module with the fix, :lucene:analysis:smartcn:test with assertions on: 22 tests, 0 failures (TestSmartChineseAnalyzer 19, TestHMMChineseTokenizerFactory 2, the new test 1).
  • :lucene:analysis:smartcn:check -x test (formatting, ecj lint, forbidden APIs) passes with the fix and the test.
  • On a9779ef3c193 the same change made the broader 7-test check pass 7 of 7 (assertions on and off) and the version driver report the bug absent.

B. Name the 14 characters in the SPACE_LIKE test (validated in standalone runs only)

Same result as A without the UnicodeProps dependency. With the patched class applied, the minimal test passes and the broader 7-test check passes 7 of 7 on 5adff78bb168; no gradle module run.

    // VT, FF, OGHAM SPACE MARK and EN QUAD to HAIR SPACE also act as a space
    if (ch == 0x000B || ch == 0x000C || ch == 0x1680 || (ch >= 0x2000 && ch <= 0x200A))
      return CharType.SPACE_LIKE;

Trade-offs

A hand-kept list instead of Lucene's maintained Unicode set.

C. Character.isSpaceChar in the SPACE_LIKE test (not recommended)

The finder's first sketch. With it the broader 7-test check still fails 4 of 7.

Trade-offs

Misses VT and FF (it covers only Zs, Zl and Zp); also turns U+00A0, U+202F, U+205F, U+2028 and U+2029 from DELIMITER into SPACE_LIKE; depends on the runtime JDK's Unicode tables. LUCENE-6874 (#7932) chose the White_Space property over Character.isSpaceChar for the same reasons.

D. Add the 14 characters to stopwords.txt (not recommended)

Removes the terms for users of the default stop list only.

Trade-offs

Leaves a position gap like removed punctuation, so the exact phrase still misses, and 中<U+2009>国 is still not joined into 中国 (reasoning from the code, not run).

Downstream note

Products that bundle Lucene's smartcn module, such as the Elasticsearch Smart Chinese analysis plugin, inherit this behaviour, and a fix changes their indexed terms as well.

How it was found

Semi-formal: an exhaustive sweep ran every BMP character through the stock Utility.getCharType and compared its class with its Unicode category. Of the 17 space separators, 2 are SPACE_LIKE, 3 DELIMITER and 12 OTHER; each was then run through SmartChineseAnalyzer. A later check restated the scope over Unicode White_Space: 14 characters become terms.

The method in full124 words

Method: semi-formal, exhaustive over the BMP character table.

  • A sweep ran all 65,536 BMP characters through the stock Utility.getCharType on the main jars and cross-tabulated the class against the JDK 25 Unicode general category. For the space separators (Zs, 17 characters): SPACE_LIKE 2, DELIMITER 3, OTHER 12.
  • Each space separator was then driven through the stock SmartChineseAnalyzer and its terms printed; the OTHER ones came out as one-character terms.
  • The finding was reduced to a public-API JUnit test on the real jars.
  • The confirming check restated the scope over the Unicode White_Space property (Lucene's pinned UnicodeProps.WHITESPACE, checked over the whole BMP): that added VERTICAL TAB and FORM FEED and left out U+00A0, U+202F, U+205F, U+0085, U+2028 and U+2029, which behave like punctuation.

Prior reports, history and checks

Prior reports

New: no Lucene issue, PR, JIRA entry, list thread or commit, and nothing outside Lucene, describes this defect (re-checked 2026-11-03). Related items concern other things: #3089, a position bug where rmuir described the stop-list design; #2802, a refactoring wish; and 2017 Wikimedia notes about ZERO WIDTH SPACE, which is not whitespace.

Searches5 searches

No report of this defect (re-checked 2026-11-03 in two independent passes, and again for this doc). Related prior items, none of them this defect:

  • #3089 (LUCENE-2014, 2009, fixed): a position-increment bug (a missing clearAttributes). In it rmuir described the design: smartcn "creates individual tokens for each piece of punctuation (including things like whitespace), and puts these in the stopword list". It names no character and reports no whitespace term; space, tab, CR, LF and U+3000 produce no token, then and now.
  • #2802 (LUCENE-1728, 2009, closed): moving smartcn to its own module; rmuir listed "use of unicode categories (java Character class, etc) versus Utility.getCharType()" as a refactoring wish. No defect is named.
  • The Wikimedia Foundation search team's 2017 SmartCN evaluation notes (mediawiki.org, "User:TJones (WMF)/Notes/Chinese Analyzer Analysis", section added 2017-04-27): they note that SmartCN splits words at ZERO WIDTH SPACE U+200B (台[ZWSP]儿庄 -> 台 + 儿 + 庄). U+200B is a format character, not White_Space, and the fix here does not change it; the notes name none of the 14 characters, no whitespace term, no search effect and no cause, and they call the no-break-space handling "Good".
  • #3098 (LUCENE-2023, open): a performance patch, never committed, that keeps the same five space characters.
  • #7932 / #6160 (LUCENE-6874, LUCENE-5096): WhitespaceTokenizer and the no-break space, resolved by adding UnicodeWhitespaceTokenizer; the precedent for using the White_Space property instead of Character.isSpaceChar.
  • #9372 (LUCENE-8325, fixed in 7.4.0): surrogates in getCharType, a different character class; a precedent for fixing this table as a bug.
  • #5795 (LUCENE-4730): offsets with trailing ASCII spaces, fixed; unrelated.

LUCENE-6874 is the precedent for the choice of character set. LFV-707 is a different bug in the same method (its DELIMITER ranges).

What was searched, when, and what turned up
WhereWhenHowFound
GitHub apache/lucene issues, PRs and commits (incl. the migrated JIRA archive); downstream repositories; dev@, java-user@, issues@, commits@; JIRA2026-10-27the scripted prior-report search, 6 runs: 154 GitHub issue and PR, 15 commit, 10 downstream, 100 mailing-list and 20 JIRA queriesonly the related items above
GitHub by hand: apache/lucene-solr, apache/solr, Lucene.NET, Elasticsearch, OpenSearch, the Elasticsearch smartcn plugin, all of GitHub; JIRA LUCENE and SOLR; lists.apache.org2026-10-2790 read-only GitHub searches; 48 JQL queries with 21 issues read in full; 65 list-archive queries with 6 threads readnothing about these characters in smartcn
Open PRs; local full history; web and Stack Overflow2026-10-27the changed-file lists of all 410 open apache/lucene PRs; pickaxe and message searches; 16 web and 4 Stack Overflow searchesno open PR touching smartcn code found; the SPACE_LIKE test never changed; the 2017 Wikimedia notes
Re-check for this doc: GitHub issues, PRs and commits, downstream trackers, the four lists, JIRA, web2026-11-03the scripted prior-report search, 51 queries (16 GitHub, 3 commit, 2 downstream, 20 list, 4 JIRA, 6 web planned), 178 hits; open smartcn PRs and smartcn issues or PRs since 2026-10-01; the latest upstream smartcn commits; 3 web searchesnothing new; the latest smartcn commit upstream, 54283150a81 (2026-06-14), is in 5adff78bb168
GitHub apache/lucene issues and PRs2026-11-04gh search for smartcn (latest updated first), THIN SPACE, EM SPACE, SPACE_LIKE, getCharType, "smartcn whitespace" and "SmartChineseAnalyzer space"; open smartcn PRsnothing new (only #2802 and #9372, both above)

History

In the original contribution (LUCENE-1629, e01aad89fe2, 2009-05-14), first released in 2.9.0; the SPACE_LIKE test has never changed. A version driver finds the bug on 24 releases from 2.9.0 to 10.5.2; the minimal test fails on 9.1.0, 9.12.3, 10.5.2, 10.6.0 and main. Not fixed upstream.

Versions tested8 rows

Introduced by the original contribution, LUCENE-1629 "contrib intelligent Analyzer for Chinese" (GitHub #2703), a JIRA patch committed on 2009-05-14 as e01aad89fe2 (svn r774718); no GitHub PR exists. git log -S/-G on the SPACE_LIKE condition, return CharType.OTHER, the segmenter's SPACE_LIKE case and its STRING default branch each return only this commit. Not a regression: the later commits on getCharType (5265dc1bb20 LUCENE-1722 comment translation, 55858d7ba72 LUCENE-8325 surrogate check in 7.4.0, 7f8b7ffbcad LUCENE-9570 reformatting) left the test and the fall-through unchanged. 2.4.1, the release before 2.9.0, has no cn.smart package, so no release ever shipped an unaffected SmartChineseAnalyzer.

The version-portable driver checks three things for each of the 14 characters c: hello+c+world and 中+c+国 give a whitespace-only term (28 inputs), world is not right after hello (14), and 中+c+国 does not give 中国 (14); its controls are space, tab, CR, LF and U+3000. Its term lists are byte-identical on every release run. The driver checks terms and positions; the phrase and TermQuery searches themselves ran in the confirming 7-test check on main, 10.5.2 and 9.12.3.

Versions and branches executed, with results
Version or commitVerdictResult
2.4.1 no APIno org.apache.lucene.analysis.cn.smart package (the probe does not compile)
2.9.0 first releasedriver: 28/28 whitespace terms, 14/14 with world not right after hello (so the phrase breaks), 14/14 words not joined; controls hold
2.9.4, 3.0.0, 3.0.3, 3.1.0, 3.6.2, 4.0.0, 4.7.2, 4.8.0, 4.10.4, 5.0.0, 5.5.5, 6.0.0, 6.6.6, 7.0.0, 7.3.1, 7.4.0, 7.7.3, 8.0.0, 8.11.4, 9.0.0 affecteddriver: the same, identical term lists (both sides of the 4.8.0, 6.0.0 and 7.4.0 pipeline changes)
9.1.0, 9.12.3 affectedminimal test fails; driver (9.12.3, assertions on and off) the same
10.0.0, 10.5.2 affecteddriver the same; minimal test fails on 10.5.2
10.6.0 affectedminimal test fails, assertions on and off
main 5adff78bb168 affectedminimal test fails (gradle and the JUnit runner, assertions on and off, 20 of 20 iterations); 7-test check 4 of 7 fail
main + fix A not affectedrepro passes; smartcn module 22 tests pass; driver (on a9779ef3c193) reports the bug absent

Independent checks

Before this doc: the finder's cross-model review (OpenAI GPT-5.6) and an independent reproducer rated it real; a GPT-5.6 refute review reproduced it but called it an enhancement; a devil's-advocate verifier rated it real; the adjudication sent it to a tie-breaker, which confirmed it (medium confidence) for the 14 characters. This doc re-ran it on 5adff78bb168.

Checks and verdicts339 words

The reviews and verifiers ran on main a9779ef3c193 (the cross-model reviews on ea57360912ed, whose smartcn sources are identical); a re-verification on e1faeba08bde (2026-11-02) and this doc's runs on 5adff78bb168 reproduced it.

Each independent check and its verdict
CheckVerdictWhat it found
finder found (scope later narrowed)BMP sweep, then a 2-test JUnit: both fail with assertions on and off, also on 10.5.2 and 9.12.3. Its claim also covered U+00A0, U+202F and U+205F, which are removed like punctuation; that part was not confirmed.
cross-model review (OpenAI GPT-5.6, intended lens, executed) real (high)Reproduced on main, 10.5.2 and 9.12.3; rated the intended-behaviour case moderate; advised a pinned Unicode set over Character.isSpaceChar.
independent reproducer realOwn public-API test: 3 of 3 fail on main (assertions on and off), 10.5.2 and 9.12.3, controls pass; StandardAnalyzer, CJKAnalyzer and WhitespaceAnalyzer emit no whitespace-only term.
refute review (OpenAI GPT-5.6, executed) not real (high): an enhancementReproduced the behaviour and agreed on root cause and fix, but argued no contract promises Unicode-space handling (see the devil's advocate above).
devil's-advocate verifier real (medium-high)No surviving intended reading for the whitespace terms; found that &nbsp; decodes to U+0020, so it is not a trigger.
adjudication disputed (medium)Re-ran the independent test (fails with assertions on and off, passes with a fix applied) and sent the case to a tie-breaker because the refute argument was substantive.
tie-breaker confirmed (medium), narrowedOwn 7-test JUnit: 4 of 7 fail on main, 10.5.2 and 9.12.3, controls pass; answered the refute review point by point; fix A passes 7 of 7 and the 21 upstream smartcn tests.
re-checks still reproducesClean re-runs on a9779ef3c193 and main e1faeba08bde (2026-11-02): 4 of 7 fail with assertions on and off; fix A passes.
this doc reproduced; fix validatedOne-method repro fails on main 5adff78bb168 (gradle and the JUnit runner, assertions on and off, 20 of 20 iterations) and on the 10.6.0, 10.5.2, 9.12.3 and 9.1.0 jars; fix A passes it and the smartcn module.

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

Finding record

LFV-728, snapshot of 2026-11-06

Registry title
SmartChineseAnalyzer indexes whitespace characters as terms: VERTICAL TAB, FORM FEED, OGHAM SPACE MARK and the eleven spaces U+2000-U+200A (EN QUAD to HAIR SPACE, among them EN, EM and THIN SPACE) each become a one-character term, because Utility.getCharType classifies them OTHER instead of SPACE_LIKE
Area
analysis-smartcn / HHMM segmenter character classes (Utility.getCharType SPACE_LIKE test -> HHMMSegmenter OTHER branch -> one-character STRING term; SmartChineseAnalyzer and HMMChineseTokenizer)
Priority
Medium, rank 146: The stock SmartChineseAnalyzer indexes 14 rare Unicode spaces as terms, which breaks phrases that cross one of them, a rare-input relevance error.
Impact class
silent wrong results
Impact note
Only users of the optional smartcn module (SmartChineseAnalyzer with any constructor, or the HMMChineseTokenizer it wraps; default settings, no scale) whose documents or queries contain one of the 14 characters are hit: a whitespace-only term is indexed and a TermQuery for that character finds the document, an exact phrase typed with an ordinary space misses the words on both sides of it (slop 1 still matches), and Hanzi are no longer joined into a word across it ('中 国' -> [中国], '中<U+2009>国' -> [中, U+2009, 国]); HTML run through Lucene's own HTMLStripCharFilter triggers it with &emsp; &ensp; and &thinsp; while &nbsp; does not (it decodes to U+0020); nothing throws, the index stays valid, -ea and -da behave the same, and because a fix changes indexed terms, affected fields need reindexing after it.
Summary
You index text with the stock SmartChineseAnalyzer, whose segmenter has a character class for 'Characters that act as a space' (CharType.SPACE_LIKE) and skips those characters, so you expect any space to separate words without a trace, as an ordinary space, a tab or the ideographic space U+3000 does. Instead Utility.getCharType knows only those five, and VERTICAL TAB, FORM FEED, OGHAM SPACE MARK and U+2000-U+200A fall through to OTHER and are each indexed as a one-character term: 'hello<THIN SPACE>world' gives [hello, U+2009, world], a TermQuery for U+2009 alone finds the document, and '中<U+2009>国' gives [中, U+2009, 国] where '中 国' gives [中国]. So the exact phrase "hello world" matches only 3 of 7 documents that differ only in the separator (space, tab and U+3000 match; FORM FEED, U+1680, EM SPACE and THIN SPACE miss), and HTML indented with &emsp;&emsp; gets two whitespace terms, with no error.
Introduced
e01aad89fe24f2482eb2e8c0e39f8272704abe80 (LUCENE-1629 'contrib intelligent Analyzer for Chinese', GitHub #2703: the original SmartChineseAnalyzer contribution, a JIRA patch committed as svn r774718; no GitHub PR exists) [read: git log -S and -G on the SPACE_LIKE condition, 'return CharType.SPACE_LIKE', 'return CharType.OTHER', Utility.SPACES, 'case CharType.SPACE_LIKE', the HHMMSegmenter join loop and the default branch's STRING token each return only this commit; git blame and git log -L of getCharType in the full-history clone]. Not a regression: the later commits on getCharType (5265dc1bb20 LUCENE-1722 comment translation, 55858d7ba72 LUCENE-8325 surrogate check in 7.4.0, 7f8b7ffbcad LUCENE-9570 reformatting) left the SPACE_LIKE test and the OTHER fall-through unchanged (2009-05-14 (first release 2.9.0))
First affected version
2.9.0 [exec] (the first release with the org.apache.lucene.analysis.cn.smart package; 2.4.1, the release before, has no such package [exec: the API probe does not compile], so no release ever shipped an unaffected SmartChineseAnalyzer)
Affected versions
Every release from 2.9.0 to 10.6.0 and main a9779ef3c193; not fixed. [exec] the minimal one-method test fails on the released 10.6.0 jars with -ea and -da (2026-11-03); a version-portable driver reports the bug fully present (28 of 28 inputs give a whitespace-only term, 14 of 14 break the exact phrase, 14 of 14 stop 中国 from being joined; controls hold) with byte-identical term lists on 24 releases (2.9.0, 2.9.4, 3.0.0, 3.0.3, 3.1.0, 3.6.2, 4.0.0, 4.7.2, 4.8.0, 4.10.4, 5.0.0, 5.5.5, 6.0.0, 6.6.6, 7.0.0, 7.3.1, 7.4.0, 7.7.3, 8.0.0, 8.11.4, 9.0.0, 9.12.3, 10.0.0, 10.5.2) and on main, with -ea and (9.12.3, 10.5.2, main) -da, and reports it absent on main with the tie-breaker's fix applied; the result is the same on both sides of the boundaries 4.7.2/4.8.0 (LUCENE-4984, HMMChineseTokenizer), 5.5.5/6.0.0 (LUCENE-5969, SentenceTokenizer removed) and 7.3.1/7.4.0 (LUCENE-8325); the tie-breaker's JUnit fails 4 of 7 (its 3 controls pass) and the finder's 2 of 2 on 9.1.0, 9.12.3, 10.0.0, 10.5.2 and main (neither compiles on 9.0.0, which predates org.apache.lucene.tests). [read] branch_10_6, branch_10x, branch_10_5 and upstream main a95c754ee00 have the same SPACE_LIKE test and OTHER fall-through (read 2026-10-27).
Status
documented (brief, checks and a per-finding doc exist)
Verification
Confirmed by AI-run checks: an independent repro, a cross-model review that disputed it, an adjudication that rated it disputed and a tie-breaker that confirmed it (medium confidence), an intended-behaviour check, a prior-report search and a skeptical audit; not yet triaged by a person.
Found by
semi-formal: exhaustive check
Upstream and prior reports
no Lucene report found (searched 2026-10-27, read-only; re-checked 2026-11-03): six scripted prior-report searches (154 GitHub issue and PR, 15 commit, 10 downstream, 100 mailing-list and 20 JIRA queries), 90 manual read-only GitHub searches (apache/lucene-solr, apache/solr, apache/lucenenet, Elasticsearch, OpenSearch, the Elasticsearch smartcn plugin and all of GitHub), 48 JQL queries over LUCENE and SOLR with 21 issues read in full, 65 lists.apache.org queries, the changed-file lists of all 410 open apache/lucene PRs, the local full history, and 16 web plus 4 Stack Overflow searches. No issue, PR, JIRA ticket, list thread or commit reports or fixes how smartcn handles VERTICAL TAB, FORM FEED, U+1680 or U+2000-U+200A (nor the no-break spaces), and no open PR touches smartcn code (#202 changes a javadoc word, #681 module-info). Related, outside Lucene's trackers (a different defect): the Wikimedia Foundation search team's 2017 SmartCN evaluation notes (mediawiki.org, User:TJones (WMF)/Notes/Chinese Analyzer Analysis, section added 2017-04-27) say SmartCN splits words at ZERO WIDTH SPACE U+200B, a format character that is not White_Space and that this fix does not change, and that no-break spaces 'get tokenized separately' (judged 'Good'). Related, not the same bug: #3089 (LUCENE-2014, fixed 2009: rmuir wrote that smartcn makes tokens for punctuation 'including things like whitespace' and puts these in the stop list), #2802 (LUCENE-1728, closed: 'use of unicode categories ... versus Utility.getCharType()' as a refactoring wish), #3098 (LUCENE-2023, open: an uncommitted patch that keeps the same five space characters), #7932 and its duplicate #6160 (LUCENE-6874, LUCENE-5096: WhitespaceTokenizer and NBSP, resolved by adding UnicodeWhitespaceTokenizer; precedent for the White_Space property over Character.isSpaceChar), #5795 (LUCENE-4730: offsets with trailing ASCII spaces, fixed). Precedent: #9372 (LUCENE-8325, fixed in 7.4.0), another getCharType misclassification fixed as a bug.
Lucene commit tested
main 5adff78bb168 (gradle in a scratch worktree and the JUnit runner, assertions on and off) and the released 10.6.0, 10.5.2, 9.12.3 and 9.1.0 jars, 2026-11-03. Earlier runs: main a9779ef3c193 (identical smartcn sources) and e1faeba08bde; a version-portable driver on 24 releases from 2.9.0 to 10.5.2.

Lucene and upstream sources

Finding record
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/Utility.java:41-44 (at a9779ef3c193) (SPACES javadoc 'Space-like characters that need to be skipped: such as space, tab, newline, carriage return.'), :140-159 (getCharType; SPACE_LIKE only for ' ', TAB, CR, LF, U+3000 at :146-147; '// Punctuation Marks' DELIMITER ranges at :148-151 and :157; 'return CharType.OTHER' at :158)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/CharType.java:38-39 (at a9779ef3c193) (SPACE_LIKE 'Characters that act as a space'), :47-48 (OTHER 'Other (not fitting any of the other categories)'), :22 (@lucene.experimental)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/hhmm/HHMMSegmenter.java:56-58 (at a9779ef3c193) (SPACE_LIKE skipped), :92 (Hanzi prefix walk joins across SPACE_LIKE), :156-165 (default branch: one-character WordType.STRING token; comment 'any symbol not in GB2312 is treated as one of these')
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/WordSegmenter.java:69-75 (at a9779ef3c193) (convertSegToken copies the original character back into a STRING token)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/SmartChineseAnalyzer.java:33 (at a9779ef3c193) ('an analyzer for Chinese or mixed Chinese-English text'), :47 (@lucene.experimental), :124-135 (HMMChineseTokenizer + PorterStemFilter + StopFilter)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/HMMChineseTokenizerFactory.java:27-30 (at a9779ef3c193) (punctuation tokens are to be removed with the SmartChinese stop list)
  • lucene/analysis/smartcn/src/resources/org/apache/lucene/analysis/cn/smart/stopwords.txt:54-55 (at a9779ef3c193) ('the line below contains an IDEOGRAPHIC SPACE character (Used as a space in Chinese)'; no entry for the 14 characters)
  • lucene/analysis/common/src/java/org/apache/lucene/analysis/util/UnicodeProps.java:33-40 (at a9779ef3c193) (UNICODE_VERSION 17.0.0.0; WHITESPACE, 25 code points)
  • lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/HTMLCharacterEntities.jflex:109 (at a9779ef3c193) ('emsp' -> U+2003, 'ensp' -> U+2002), :124 ('nbsp' -> ' '), :145 ('thinsp' -> U+2009)
  • lucene/analysis/smartcn/src/test/org/apache/lucene/analysis/cn/smart/TestSmartChineseAnalyzer.java:119-128 (at a9779ef3c193) (testChineseStopWords2, posInc 2 after removed punctuation), :182-186 (testNonChinese comment '(regardless of Unicode category)')
  • SECURITY.md (In-scope reports; Untrusted query and analysis input; Scope and Threat Model)
The finding in 30 seconds
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/Utility.java:140-159 (at 5adff78bb168) (:146-147 SPACE_LIKE, :148-151 and :157 DELIMITER ranges, :158 OTHER)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/CharType.java:38-39, (at 5adff78bb168) :47-48
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/hhmm/HHMMSegmenter.java:56-58, (at 5adff78bb168) :92, :156-165
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/WordSegmenter.java:69-75 (at 5adff78bb168)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/SmartChineseAnalyzer.java:103-104, (at 5adff78bb168) :124-135
  • lucene/analysis/smartcn/src/resources/org/apache/lucene/analysis/cn/smart/stopwords.txt:54-55 (at 5adff78bb168)
  • lucene/analysis/common/src/java/org/apache/lucene/analysis/util/UnicodeProps.java:33-40 (at 5adff78bb168)
  • lucene/analysis/smartcn/src/test/org/apache/lucene/analysis/cn/smart/TestSmartChineseAnalyzer.java:119-128 (at 5adff78bb168) (testChineseStopWords2, posInc 2 after removed punctuation)
Who is affected
  • lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/HTMLCharacterEntities.jflex:109 (at 5adff78bb168) (emsp, ensp), :124 (nbsp -> ' '), :145 (thinsp)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/HMMChineseTokenizerFactory.java:27-30 (at 5adff78bb168)
  • lucene/core/src/java/org/apache/lucene/index/IndexingChain.java:2055 (at 5adff78bb168) (each token adds 1 to the field length)
Minimal repro
  • Lucene main 5adff78bb168 build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java:240-248 (tests.asserts default drawn from the project seed); build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/globals/RegisterBuildGlobalsPlugin.java:137-140 (project seed = root seed XOR project path hash; for :lucene:analysis:smartcn and DEADBEEF the default is false, computed in jshell)
Why it looks unintended
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/CharType.java:38-39, (at 5adff78bb168) :47-48; Utility.java:41-44
  • lucene/analysis/smartcn/src/resources/org/apache/lucene/analysis/cn/smart/stopwords.txt:54-55 (at 5adff78bb168)
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/HMMChineseTokenizerFactory.java:27-30 (at 5adff78bb168)
  • lucene/analysis/smartcn/src/test/org/apache/lucene/analysis/cn/smart/TestSmartChineseAnalyzer.java:182-185 (at 5adff78bb168) (testNonChinese)
  • https://github.com/apache/lucene/issues/3089 (LUCENE-2014, rmuir's design remark)
  • https://github.com/apache/lucene/issues/9372 (LUCENE-8325, fixed in 7.4.0)
Suggested fix
  • lucene/analysis/smartcn/src/java/module-info.java:21; (at 5adff78bb168) lucene/analysis/smartcn/build.gradle:24
  • https://github.com/apache/lucene/issues/7932 (LUCENE-6874)
  • JDK java.lang.Character#isWhitespace javadoc (names U+00A0, U+2007 and U+202F as non-breaking spaces) and #isSpaceChar (Zs, Zl, Zp only)
Prior reports
  • https://github.com/apache/lucene/issues/3089; https://github.com/apache/lucene/issues/2802; https://www.mediawiki.org/wiki/User:TJones_(WMF)/Notes/Chinese_Analyzer_Analysis
Diagrams
  • lucene/analysis/smartcn/src/java/org/apache/lucene/analysis/cn/smart/Utility.java:146-147, (at 5adff78bb168) :158; hhmm/HHMMSegmenter.java:56-58, :156-165

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

Repro files

About the diagrams

A walk-through of the minimal repro's input, made from the code at 5adff78bb168 and the executed runs; the PNG is the summary still.

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.