gastownhall/beads · error

unknown field: %s

Error message

unknown field: %s

What it means

The beads query evaluator only accepts comparison fields from a fixed list (status, priority, type, assignee, owner, label(s), title, description, notes, created/updated/closed/started timestamps, id, spec, parent, pinned, ephemeral, template, mol_type, has_metadata_key, plus any field prefixed with "metadata."). When applyComparison sees a field name outside that set and not a metadata. prefix, it rejects the whole query with this error. It is a query-authoring validation error, not a runtime/storage failure.

Source

Thrown at internal/query/evaluator.go:205

	case "spec", "spec_id":
		return e.applySpecFilter(comp, filter)
	case "parent":
		return e.applyParentFilter(comp, filter)
	case "pinned":
		return e.applyBoolFilter(comp, filter, "pinned")
	case "ephemeral":
		return e.applyBoolFilter(comp, filter, "ephemeral")
	case "template":
		return e.applyBoolFilter(comp, filter, "template")
	case "mol_type":
		return e.applyMolTypeFilter(comp, filter)
	case "has_metadata_key":
		return e.applyHasMetadataKeyFilter(comp, filter)
	default:
		if strings.HasPrefix(comp.Field, "metadata.") {
			return e.applyMetadataFilter(comp, filter)
		}
		return fmt.Errorf("unknown field: %s", comp.Field)
	}
}

func (e *Evaluator) applyStatusFilter(comp *ComparisonNode, filter *types.IssueFilter) error {
	if comp.Op != OpEquals && comp.Op != OpNotEquals {
		return fmt.Errorf("status only supports = and != operators")
	}
	status := types.Status(strings.ToLower(comp.Value))
	if !status.IsValid() {
		return fmt.Errorf("invalid status: %s", comp.Value)
	}
	if comp.Op == OpEquals {
		filter.Status = &status
	} else {
		filter.ExcludeStatus = append(filter.ExcludeStatus, status)
	}
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the spelling of the field against the switch in internal/query/evaluator.go:158-200 (applyComparison) and correct it.
  2. If filtering on a custom metadata entry, prefix the key with "metadata." (e.g. metadata.team = ops) so it routes to applyMetadataFilter.
  3. If the field genuinely should exist, add a case in applyComparison and a corresponding applyXxxFilter implementation — do not try to work around it client-side.
  4. Run `bd schema` (or inspect types.IssueFilter) to see which fields are filterable before writing the query.

Example fix

// before (typo'd / unknown field)
filter, err := query.Parse("statues = open")
// after
filter, err := query.Parse("status = open")
// custom metadata field:
// before: "team = ops"
// after:  "metadata.team = ops"
Defensive patterns

Strategy: validation

Validate before calling

var validFields = map[string]bool{"status":true,"priority":true,"type":true,"assignee":true,"owner":true,"label":true,"labels":true,"title":true,"description":true,"desc":true,"notes":true,"created":true,"created_at":true,"updated":true,"updated_at":true,"closed":true,"closed_at":true,"started":true,"started_at":true,"id":true,"spec":true,"spec_id":true,"parent":true,"pinned":true,"ephemeral":true,"template":true,"mol_type":true,"has_metadata_key":true}
func validQueryField(f string) bool { return validFields[f] || strings.HasPrefix(f, "metadata.") }

Type guard

func isComparisonNode(n query.Node) (*query.ComparisonNode, bool) { c, ok := n.(*query.ComparisonNode); return c, ok }

Try / catch

if err := evaluator.Apply(node, filter); err != nil {
    var qe *query.Error
    if errors.As(err, &qe) && strings.HasPrefix(qe.Msg, "unknown field:") {
        return fmt.Errorf("query field %q is not filterable; see bd schema", field)
    }
    return err
}

Prevention

When it happens

Trigger: Calling the query evaluator (bd list/filter queries) with a ComparisonNode whose Field is not one of the recognized names — e.g. typos like "statues", "priorty", "labels.tags", unquoted arbitrary identifiers like "assignee_email", or a foreign field name from another tool's query language (JQL/SOQL style).

Common situations: Typos in hand-written queries; copying query syntax from GitHub/Jira where fields like "milestone" or "sprint" exist but not in beads; schema drift after renaming a field in a script; assuming custom issue fields are queryable without the required "metadata." prefix.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/76175d438204c7e7. Report an issue: GitHub.