gastownhall/beads · error

kind is required

Error message

kind is required

What it means

Append requires every audit Entry to carry a non-empty Kind discriminator and returns this error when Entry.Kind is "". Kind labels the event type (e.g. LLM call, tool call, field change) and the JSONL sidecar relies on it to be meaningful. Like the nil check, this is an input-validation error raised before any file I/O.

Source

Thrown at internal/audit/audit.go:115

		if closeErr := f.Close(); closeErr != nil {
			return "", fmt.Errorf("failed to close interactions log: %w", closeErr)
		}
		return p, nil
	}
	if !errors.Is(err, os.ErrExist) {
		return "", fmt.Errorf("failed to create interactions log: %w", err)
	}
	return p, nil
}

// Append appends an event to .beads/interactions.jsonl as a single JSON line.
// This is intentionally append-only: callers must not mutate existing lines.
func Append(e *Entry) (string, error) {
	if e == nil {
		return "", fmt.Errorf("nil entry")
	}
	if e.Kind == "" {
		return "", fmt.Errorf("kind is required")
	}

	p, err := EnsureFile()
	if err != nil {
		return "", err
	}

	if e.ID == "" {
		e.ID, err = newID()
		if err != nil {
			return "", err
		}
	}
	if e.CreatedAt.IsZero() {
		e.CreatedAt = time.Now().UTC()
	} else {
		e.CreatedAt = e.CreatedAt.UTC()
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set a descriptive Kind on the Entry before appending (e.g. "field_change", "llm_call").
  2. Define Kind values as package-level constants and use them at every construction site.
  3. Validate required fields with a small helper before calling Append.
  4. Check upstream data sources for empty kind strings.

Example fix

// before
entry := &audit.Entry{IssueID: issue.ID}
audit.AppendIfEnabled(entry) // "kind is required"
// after
entry := &audit.Entry{Kind: "field_change", IssueID: issue.ID}
audit.AppendIfEnabled(entry)
Defensive patterns

Strategy: validation

Validate before calling

if entry != nil && strings.TrimSpace(entry.Kind) == "" {
    return fmt.Errorf("audit entry requires a non-empty kind")
}

Type guard

func hasKind(e *audit.Entry) bool { return e != nil && e.Kind != "" }

Try / catch

if _, err := audit.Append(e); err != nil && strings.Contains(err.Error(), "kind is required") {
    return fmt.Errorf("entry %p built without Kind", e)
}

Prevention

When it happens

Trigger: Calling audit.Append(&audit.Entry{}) or AppendIfEnabled with an entry literal that omits Kind, or building an Entry dynamically where the Kind field is set from an empty string variable.

Common situations: Adding a new audit event type and forgetting to assign its Kind constant; zero-value struct literals; deserializing an entry from JSON that lacked "kind" and re-appending it.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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