hashicorp/nomad · error

failed to read filter expression: %v

Error message

failed to read filter expression: %v

What it means

NewPaginator wraps any error returned by bexpr.CreateEvaluator when parsing the caller-supplied filter expression string. It means the filter expression failed to parse — invalid syntax, unknown operators, or malformed expressions. The paginator is not created and the error is returned synchronously from NewPaginator.

Source

Thrown at nomad/state/paginator/paginator.go:61

	selector SelectorFunc[T],
	tokenizer Tokenizer[T],
	stubFn func(T) (TStub, error),
) (*Paginator[T, TStub], error) {

	p := &Paginator[T, TStub]{
		iter:           iter,
		tokenizer:      tokenizer,
		selector:       selector,
		stubFn:         stubFn,
		perPage:        opts.PerPage,
		reverse:        opts.Reverse,
		nextTokenFound: opts.NextToken == "",
	}

	if opts.Filter != "" {
		evaluator, err := bexpr.CreateEvaluator(opts.Filter)
		if err != nil {
			return nil, fmt.Errorf("failed to read filter expression: %v", err)
		}
		p.bexpr = evaluator
	}

	return p, nil
}

// Page populates a page by running the append function
// over all results. Returns the next token.
func (p *Paginator[T, TStub]) Page() ([]TStub, string, error) {
	out := []TStub{}
DONE:
	for {
		obj, andThen := p.next()
		switch andThen {
		case paginatorInclude:
			out = append(out, obj)
		case paginatorSkip:

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Print the wrapped underlying error (%v) to see the exact parse failure (line/column) and fix the expression syntax.
  2. Validate the expression with bexpr.CreateEvaluator in a unit test or CLI before sending it to the server.
  3. Quote string literals properly in the expression, e.g. Status == "ready" not Status == ready.
  4. If the filter is empty, pass "" instead of whitespace so the evaluator is skipped entirely.

Example fix

// before
p, err := paginator.NewPaginator(iter, nil, "Status == "+status, objs)
// after
expr := fmt.Sprintf("Status == %q", status)
p, err := paginator.NewPaginator(iter, nil, expr, objs)
Defensive patterns

Strategy: validation

Validate before calling

if filter != "" {
    if _, err := bexpr.CreateEvaluator(filter); err != nil {
        return fmt.Errorf("invalid filter expression %q: %w", filter, err)
    }
}

Try / catch

p, err := paginator.NewPaginator(iter, nil, filter, objs)
if err != nil {
    if strings.Contains(err.Error(), "failed to read filter expression") {
        // fall back to unpaginated/unfiltered view or surface a 400
    }
    return err
}

Prevention

When it happens

Trigger: Calling state.paginator.NewPaginator with opts.Filter set to a non-empty string that is not a valid bexpr expression, e.g. 'Foo ==>' or 'Status != ' (unbalanced quotes/operators), or referencing syntax bexpr does not support.

Common situations: Hand-written filter strings in API clients or Job specs with typos; dynamically built filter expressions where user input was interpolated without quoting; users copying filter syntax from other systems (e.g. Consul filter syntax) that bexpr does not accept.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/7c682e120bd9bbca. Report an issue: GitHub.