vitessio/vitess · error

unexpected in_keyrange parameter: %v

Error message

unexpected in_keyrange parameter: %v

What it means

analyzeInKeyRange parses the keyrange string argument of in_keyrange() with key.ParseShardingSpec and requires the spec to yield exactly one keyrange. A parameter that parses into zero or multiple ranges (e.g. an empty spec or an 'a-b,c-d' style multi-part spec) is rejected as unexpected for the single-filter in_keyrange form.

Source

Thrown at go/vt/vttablet/tabletserver/vstreamer/planbuilder.go:1017

		krExpr = exprs[len(exprs)-1]
	default:
		return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unexpected in_keyrange parameters: %v", sqlparser.SliceString(exprs))
	}
	var err error
	whereFilter.VindexColumns, err = buildVindexColumns(plan.Table, colnames)
	if err != nil {
		return err
	}
	kr, err := selString(krExpr)
	if err != nil {
		return err
	}
	keyranges, err := key.ParseShardingSpec(kr)
	if err != nil {
		return err
	}
	if len(keyranges) != 1 {
		return fmt.Errorf("unexpected in_keyrange parameter: %v", sqlparser.String(krExpr))
	}
	whereFilter.KeyRange = keyranges[0]
	plan.Filters = append(plan.Filters, whereFilter)
	return nil
}

func selString(expr sqlparser.Expr) (string, error) {
	val, ok := expr.(*sqlparser.Literal)
	if !ok {
		return "", fmt.Errorf("unsupported: %v", sqlparser.String(expr))
	}
	return val.Val, nil
}

// buildVindexColumns builds the list of column numbers of the table
// that will be the input to the vindex function.
func buildVindexColumns(ti *Table, colnames []sqlparser.IdentifierCI) ([]int, error) {
	vindexColumns := make([]int, 0, len(colnames))

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Pass a single keyrange literal, e.g. in_keyrange('-80') or in_keyrange('80-').
  2. Split multi-range streaming into one VStreamResults request per keyrange.
  3. Validate the string with key.ParseShardingSpec semantics before sending the query.
  4. Use the alternate form in_keyrange(col, 'hash', '-80') if a single column keyrange is what you meant.

Example fix

// before
select ... from t where in_keyrange('-80,c0-')
// after
select ... from t where in_keyrange('-80') -- one request per range
Defensive patterns

Strategy: validation

Validate before calling

// ensure the keyrange string parses to exactly one range before building the query
keyranges, err := key.ParseShardingSpec(kr)
if err != nil || len(keyranges) != 1 {
    return fmt.Errorf("in_keyrange requires exactly one keyrange, got %q", kr)
}

Type guard

func isSingleKeyRange(kr string) bool {
    krs, err := key.ParseShardingSpec(kr)
    return err == nil && len(krs) == 1
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unexpected in_keyrange parameter") {
    return fmt.Errorf("split multi-range specs into one in_keyrange() per request: %w", err)
}

Prevention

When it happens

Trigger: Calling VStreamResults with a predicate like `in_keyrange('-80,e0-')` (multi-range spec) or an empty/blank literal that parses to len(keyranges) != 1.

Common situations: Copy-pasting multi-range sharding specs from a VReplication filter config into an in_keyrange() predicate; typos like trailing commas creating multiple ranges; assuming in_keyrange accepts the same specs as Filter rules.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/da6a767426f92567. Report an issue: GitHub.