Skip to content

Bug: exact-match shortcut in BitapSearch bypasses minMatchCharLength #831

Closed

Description

@JSap0914

Issue: exact-match shortcut in BitapSearch bypasses minMatchCharLength

Bug Description

BitapSearch.searchIn() has a fast-path for the case where pattern === text (the
entire text is an exact match). This path returns isMatch: true immediately —
without checking minMatchCharLength. As a result, a document whose value
exactly equals the search pattern is always included in results, even when the
matched region is shorter than the configured minimum.

The non-exact bitap path correctly enforces minMatchCharLength via
convertMaskToIndices(..., minMatchCharLength) → sets isMatch = false when no
run is long enough. The shortcut path provides no equivalent guard.

Reproduction

import Fuse from 'fuse.js'

// Fuse.match API
const r = Fuse.match('abc', 'abc', { minMatchCharLength: 5 })
console.log(r.isMatch) // BUG: true  (expected: false — 3 chars < 5)

// Corpus search
const fuse = new Fuse(['abc', 'abcde12345'], { minMatchCharLength: 5 })
console.log(fuse.search('abc').map(r => r.item))
// BUG: ['abc']  (expected: [] — 'abc' is only 3 characters)

Fix

Add a guard in the exact-match branch of BitapSearch.searchIn():

if (text.length < this.options.minMatchCharLength) {
  return { isMatch: false, score: 1 }
}

This mirrors the behaviour of convertMaskToIndices for non-exact matches.

Verification

npx vitest run
# 374 passed (0 failed) — all existing tests untouched, 3 new tests go GREEN

Activity

  1. krisk commented on Jul 3, 2026

    @krisk
    Owner

    Fixed on main in dbb98b6. The exact-match shortcut in BitapSearch was skipping minMatchCharLength; it now enforces it the same way the fuzzy path does. Thanks @JSap0914 for the clear repro.

  2. added a commit that references this issue on Jul 3, 2026
    dbb98b6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions