projectdiscovery/katana · error

unknown similarity mode %q (want simhash, tfidf, or bm25)

Error message

unknown similarity mode %q (want simhash, tfidf, or bm25)

What it means

ParseMode validates a similarity mode string and rejects anything other than the three supported modes: simhash, tfidf, and bm25. New() calls ParseMode on Config.Mode, so constructing an Index with a misspelled or unsupported mode string fails immediately with this error.

Source

Thrown at pkg/similarity/index.go:71

	mu       sync.Mutex
	corpus   *lexicalCorpus
	sigs     []simRep
	nextID   uint64
	clusters map[string]int // stable clusterID -> accepted count
	stats    Stats
}

// ParseMode validates a mode string.
func ParseMode(s string) (Mode, error) {
	switch Mode(strings.ToLower(strings.TrimSpace(s))) {
	case "", ModeSimHash:
		return ModeSimHash, nil
	case ModeTFIDF:
		return ModeTFIDF, nil
	case ModeBM25:
		return ModeBM25, nil
	default:
		return "", fmt.Errorf("unknown similarity mode %q (want simhash, tfidf, or bm25)", s)
	}
}

// New creates an Index. Invalid/zero config fields are filled with defaults.
func New(cfg Config) (*Index, error) {
	if cfg.Mode == "" {
		cfg.Mode = DefaultMode
	}
	mode, err := ParseMode(string(cfg.Mode))
	if err != nil {
		return nil, err
	}
	cfg.Mode = mode
	if cfg.HammingDistance <= 0 {
		cfg.HammingDistance = DefaultHammingDistance
	}
	if cfg.ScoreThreshold <= 0 || cfg.ScoreThreshold > 1 {
		cfg.ScoreThreshold = DefaultScoreThreshold

View on GitHub (pinned to e3e742739c)

Solutions

  1. Set Config.Mode to one of the exact constants (ModeSimHash, ModeTFIDF, ModeBM25) instead of a raw string literal.
  2. Normalize user input: strings.ToLower(strings.TrimSpace(mode)) before calling ParseMode/New.
  3. Check the configured value against the valid list "simhash, tfidf, bm25" and correct the typo in your config file.
  4. Fall back to a default mode when the configured value fails to parse.

Example fix

// before
cfg := similarity.Config{Mode: "SimHash"}
idx, err := similarity.New(cfg) // error: unknown similarity mode
// after
mode, err := similarity.ParseMode(strings.ToLower(strings.TrimSpace(cfgRaw.Mode)))
if err != nil {
    mode = similarity.ModeSimHash
}
idx, err := similarity.New(similarity.Config{Mode: mode})
Defensive patterns

Strategy: validation

Validate before calling

func validMode(s string) bool {
    switch strings.ToLower(strings.TrimSpace(s)) {
    case "simhash", "tfidf", "bm25":
        return true
    }
    return false
}

Type guard

func isSimilarityMode(s string) bool {
    return s == similarity.ModeSimHash || s == similarity.ModeTFIDF || s == similarity.ModeBM25
}

Try / catch

idx, err := similarity.New(cfg)
if err != nil {
    if strings.Contains(err.Error(), "unknown similarity mode") {
        log.Printf("bad mode %q, falling back to simhash", cfg.Mode)
        cfg.Mode = similarity.ModeSimHash
        idx, err = similarity.New(cfg)
    }
}

Prevention

When it happens

Trigger: Passing Config{Mode: "sim-hash"}, "SIMHASH", "cosine", or any string not exactly matching ModeSimHash/ModeTFIDF/ModeBM25 to similarity.New, or the same invalid string to ParseMode directly (also exercised by TestParseMode).

Common situations: Config read from YAML/JSON where the mode value is user-supplied or typo'd; case-sensitivity surprises ("SimHash" vs "simhash"); upgrading the library and referencing a mode that was removed or renamed.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03). Data as JSON: /api/errors/7365c2675d48901c. Report an issue: GitHub.