junegunn/fzf · error
index should be the last criterion
Error message
index should be the last criterion
What it means
Within parseTiebreak's check() closure: 'index' means input order, which is only meaningful as the final tiebreaker. Once hasIndex is true, any further criterion token triggers this error, telling you index must come last in the --tiebreak list.
Source
Thrown at src/options.go:1362
return str, []criterion{byScore, byLength}, nil
}
return str, nil, errors.New("invalid scoring scheme: " + str + " (expected: default|path|history)")
}
func parseTiebreak(str string) ([]criterion, error) {
criteria := []criterion{byScore}
hasIndex := false
hasChunk := false
hasLength := false
hasBegin := false
hasEnd := false
hasPathname := false
check := func(notExpected *bool, name string) error {
if *notExpected {
return errors.New("duplicate sort criteria: " + name)
}
if hasIndex {
return errors.New("index should be the last criterion")
}
*notExpected = true
return nil
}
for _, str := range strings.Split(strings.ToLower(str), ",") {
switch str {
case "index":
if err := check(&hasIndex, "index"); err != nil {
return nil, err
}
case "chunk":
if err := check(&hasChunk, "chunk"); err != nil {
return nil, err
}
criteria = append(criteria, byChunk)
case "pathname":
if err := check(&hasPathname, "pathname"); err != nil {
return nil, errView on GitHub (pinned to bd4efa277b)
Solutions
- Move index to the end: --tiebreak length,begin,index
- Drop trailing criteria after index, or drop index if earlier ordering matters more
Example fix
# before fzf --tiebreak index,length # after fzf --tiebreak length,index
Defensive patterns
Strategy: validation
Validate before calling
TB='length,index'
IFS=',' read -ra C <<< "$TB"
LAST="${C[-1]}"
[[ "$LAST" == index ]] || grep -qxF index <(printf '%s\n' "${C[@]}") && { echo 'index must be last' >&2; exit 1; }
fzf --tiebreak "$TB" Prevention
- Convention: order criteria by decreasing importance and always put index last
- When editing a tiebreak list, insert new criteria before the trailing index
- Remember the ordering is semantically meaningful — it is not a set
When it happens
Trigger: --tiebreak index,length (index first, then more); --tiebreak begin,index,end (end appears after index). Both add criteria after index was consumed.
Common situations: Users treating the list as unordered; migrating from scripts that appended 'index' early; editing an existing comma list by inserting a criterion before the trailing index.
Related errors
- duplicate sort criteria: ${name}
- invalid sort criterion: ${str}
- at most 3 tiebreaks are allowed: ${str}
- invalid format: ${str}
- template should include at least 1 placeholder: ${str}
AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15).
Data as JSON: /api/errors/4e28a0b8da3a5dd9.
Report an issue: GitHub.