gastownhall/beads · error

invalid status %q (valid: %s)

Error message

invalid status %q (valid: %s)

What it means

ApplyStatusFilter parses a status selector (single status or comma-separated set) onto an IssueFilter. If splitting the selector yields no parts — e.g. an empty or whitespace-only string after normalization — it is rejected as invalid, listing the valid statuses (built-ins plus custom status names).

Source

Thrown at internal/workapi/list.go:499

	}
	return false
}

// ValidStatusList renders the status names a filter accepts, for error text.
func ValidStatusList(customStatusNames []string) string {
	validList := "open, in_progress, blocked, deferred, closed, pinned, hooked"
	if len(customStatusNames) > 0 {
		validList += ", " + strings.Join(customStatusNames, ", ")
	}
	return validList
}

// ApplyStatusFilter parses a status selector - one status, or a
// comma-separated OR set - onto the filter.
func ApplyStatusFilter(filter *types.IssueFilter, status string, customStatusNames []string) error {
	parts := splitStatusSelector(status)
	if len(parts) == 0 {
		return fmt.Errorf("invalid status %q (valid: %s)", status, ValidStatusList(customStatusNames))
	}
	return applyStatusParts(filter, parts, customStatusNames)
}

func applyStatusParts(filter *types.IssueFilter, parts []string, customStatusNames []string) error {
	if len(parts) == 1 {
		s := types.Status(parts[0])
		if !s.IsValidWithCustom(customStatusNames) {
			return fmt.Errorf("invalid status %q (valid: %s)", parts[0], ValidStatusList(customStatusNames))
		}
		filter.Status = &s
		return nil
	}

	for _, part := range parts {
		s := types.Status(part)
		if !s.IsValidWithCustom(customStatusNames) {
			// "all" is a real selector on its own (every status), so failing

View on GitHub (pinned to 71377f2769)

Solutions

  1. Pass a non-empty status or comma-separated list, e.g. "open" or "open,in-progress"
  2. Check that the variable feeding the status parameter is populated
  3. Use ValidStatusList(customStatusNames) to present valid choices before calling
  4. If you want every status, pass the literal selector "all" instead of an empty string

Example fix

// before
workapi.ApplyStatusFilter(&filter, status, customStatuses) // status == "  "
// after
if strings.TrimSpace(status) != "" {
    workapi.ApplyStatusFilter(&filter, status, customStatuses)
}
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(status) != "" {
    if err := workapi.ApplyStatusFilter(&filter, status, customStatusNames); err != nil { return err }
}

Try / catch

err := workapi.ApplyStatusFilter(&filter, status, customNames)
if err != nil {
    return fmt.Errorf("bad --status %q; valid: %s", status, workapi.ValidStatusList(customNames))
}

Prevention

When it happens

Trigger: Calling ApplyStatusFilter with a status string that reduces to zero parts via splitStatusSelector (empty string, only commas/whitespace) even though a status was requested.

Common situations: Passing an empty --status flag value; shell quoting yielding only whitespace; programmatic callers building a status string from a variable that is empty.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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