junegunn/fzf · error

invalid sort criterion: ${str}

Error message

invalid sort criterion: ${str}

What it means

The default branch of parseTiebreak's switch: a comma token in --tiebreak that is not one of index|chunk|length|begin|end|pathname (after lowercasing) is rejected. Typical victims are typos, plurals, and criteria from newer/older fzf versions.

Source

Thrown at src/options.go:1399

			}
			criteria = append(criteria, byPathname)
		case "length":
			if err := check(&hasLength, "length"); err != nil {
				return nil, err
			}
			criteria = append(criteria, byLength)
		case "begin":
			if err := check(&hasBegin, "begin"); err != nil {
				return nil, err
			}
			criteria = append(criteria, byBegin)
		case "end":
			if err := check(&hasEnd, "end"); err != nil {
				return nil, err
			}
			criteria = append(criteria, byEnd)
		default:
			return nil, errors.New("invalid sort criterion: " + str)
		}
	}
	if len(criteria) > 4 {
		return nil, errors.New("at most 3 tiebreaks are allowed: " + str)
	}
	return criteria, nil
}

func dupeTheme(theme *tui.ColorTheme) *tui.ColorTheme {
	dupe := *theme
	return &dupe
}

func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, *tui.ColorTheme, error) {
	var err error
	var baseTheme *tui.ColorTheme
	theme := dupeTheme(defaultTheme)
	rrggbb := regexp.MustCompile("^#[0-9a-fA-F]{6}$")

View on GitHub (pinned to bd4efa277b)

Solutions

  1. Use only index|chunk|length|begin|end|pathname: --tiebreak pathname,length
  2. Do not include score — it is always the primary criterion
  3. Remove trailing/double commas that create empty tokens
  4. Check fzf --help for the exact spelling in your version

Example fix

# before
fzf --tiebreak score,length
# after
fzf --tiebreak length
Defensive patterns

Strategy: type-guard

Validate before calling

VALID='index chunk length begin end pathname'
IFS=',' read -ra C <<< "$(tr 'A-Z' 'a-z' <<< "$TB")"
for c in "${C[@]}"; do grep -qw "$c" <<< "$VALID" || { echo "invalid criterion: $c" >&2; exit 1; }; done
fzf --tiebreak "$TB"

Type guard

isValidFzfTiebreak() { [[ "$1" =~ ^(index|chunk|length|begin|end|pathname)$ ]]; }

Prevention

When it happens

Trigger: --tiebreak chars (not a criterion), --tiebreak lengths (plural), --tiebreak score (score is implicit and not allowed), --tiebreak time, empty tokens from a trailing comma.

Common situations: Assuming --tiebreak score works since output is score-ordered; using 'pathname' vs 'path' inconsistently; version skew where a criterion name changed between releases; trailing commas in generated options.

Related errors


AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15). Data as JSON: /api/errors/2632dd89f74ac355. Report an issue: GitHub.