gastownhall/beads · error · issueops.ErrValidation

%w: apply batch item %d has unknown kind %q

Error message

%w: apply batch item %d has unknown kind %q

What it means

The item's Kind field must be one of the known kinds (ItemCreate, ItemUpdate, ItemClose, ItemDepAdd). An unrecognized Kind hits the switch's default case and fails with the index and the offending kind string, wrapped with issueops.ErrValidation.

Source

Thrown at internal/storage/batch_apply.go:137

				payloads++
			}
		}
		if payloads != 1 {
			return nil, fmt.Errorf("%w: apply batch item %d must carry exactly one payload, got %d",
				issueops.ErrValidation, i, payloads)
		}
		var matches bool
		switch item.Kind {
		case issueops.ItemCreate:
			matches = item.Create != nil
		case issueops.ItemUpdate:
			matches = item.Update != nil
		case issueops.ItemClose:
			matches = item.Close != nil
		case issueops.ItemDepAdd:
			matches = item.DepAdd != nil
		default:
			return nil, fmt.Errorf("%w: apply batch item %d has unknown kind %q", issueops.ErrValidation, i, item.Kind)
		}
		if !matches {
			return nil, fmt.Errorf("%w: apply batch item %d is kind %q but carries another kind's payload",
				issueops.ErrValidation, i, item.Kind)
		}
		if item.Create == nil {
			continue
		}
		if item.Create.Issue == nil {
			return nil, fmt.Errorf("%w: apply batch item %d requires an issue", issueops.ErrValidation, i)
		}
		if len(item.Create.Issue.Comments) > 0 || len(item.Create.Issue.Dependencies) > 0 {
			return nil, fmt.Errorf("%w: apply batch item %d must not carry comments or dependencies on the issue; edges are their own items",
				issueops.ErrValidation, i)
		}
		if item.Create.Key == "" {
			continue
		}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Use the exported constants (issueops.ItemCreate, etc.) instead of raw strings.
  2. Fix the kind string to exactly match one of the supported constants.
  3. Check for API version drift if the kind was valid in an older version.

Example fix

// before
item := issueops.ApplyBatchItem{Kind: "create", Create: cr}
// after
item := issueops.ApplyBatchItem{Kind: issueops.ItemCreate, Create: cr}
Defensive patterns

Strategy: validation

Validate before calling

switch it.Kind {
case issueops.ItemCreate, issueops.ItemUpdate, issueops.ItemClose, issueops.ItemDepAdd:
    // ok
default:
    return fmt.Errorf("unknown kind %q", it.Kind)
}

Type guard

func knownKind(k issueops.ItemKind) bool {
    switch k {
    case issueops.ItemCreate, issueops.ItemUpdate, issueops.ItemClose, issueops.ItemDepAdd:
        return true
    }
    return false
}

Try / catch

_, err := storage.PlanApplyBatch(req)
if errors.Is(err, issueops.ErrValidation) && strings.Contains(err.Error(), "unknown kind") {
    return fmt.Errorf("unsupported batch item kind: %w", err)
}

Prevention

When it happens

Trigger: Setting Kind to a typo'd or made-up string (e.g. "creat", "delete"), or a zero-value Kind when the kind enum uses non-zero string constants.

Common situations: Hand-written JSON batches with an invalid kind; code written against an older/newer API where kinds changed; structs built without initializing Kind.

Related errors


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