Skip to content

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

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

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