JuliusBrussee/caveman · error

history requires memory id

Error message

history requires memory id

What it means

History(id) rejects an empty or whitespace-only memory id before touching the database. It is a plain precondition check: the history walk needs a concrete starting memory, and an blank id would otherwise surface as a confusing 'not found' or full-table scan downstream.

Source

Thrown at mem/store.go:279

		Text:       newText,
		CreatedAt:  now,
		ValidFrom:  now,
		Supersedes: oldID,
	}, nil
}

func validateMemorySize(text string) error {
	if len(text) > MaxMemoryBytes {
		return fmt.Errorf("%w: memory is %d bytes, over the %d-byte cap", ErrMemoryTooLarge, len(text), MaxMemoryBytes)
	}
	return nil
}

// History returns the complete oldest-to-newest supersession chain containing
// id. Broken/cyclic lineage is rejected rather than returning partial history.
func (s *Store) History(id string) ([]Memory, error) {
	if strings.TrimSpace(id) == "" {
		return nil, fmt.Errorf("history requires memory id")
	}
	current, err := s.memoryByID(id)
	if err != nil {
		return nil, err
	}
	seen := map[string]bool{current.ID: true}
	var before []Memory
	cursor := current
	for cursor.Supersedes != "" {
		prev, err := s.memoryByID(cursor.Supersedes)
		if err != nil {
			return nil, fmt.Errorf("broken supersession history at %s: %w", cursor.ID, err)
		}
		if seen[prev.ID] {
			return nil, fmt.Errorf("cyclic supersession history at %s", prev.ID)
		}
		seen[prev.ID] = true
		before = append(before, prev)

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Check the caller: find where the id originates and ensure it is set before calling History
  2. Guard with strings.TrimSpace(id) != "" at the API boundary (HTTP handler, CLI flag parsing) and return a proper 'missing id' error to your own caller
  3. Default or reject early: if the id is genuinely optional in your flow, decide an explicit behavior (latest memory, or error) instead of forwarding an empty string

Example fix

// before
hist, err := store.History(memID) // memID accidentally ""

// after
if strings.TrimSpace(memID) == "" {
    return fmt.Errorf("memory id is required")
}
hist, err := store.History(memID)
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(id) == "" {
    return errors.New("memory id required")
}
hist, err := store.History(id)

Prevention

When it happens

Trigger: Calling Store.History("") or History(" ") — typically an uninitialized variable, an empty id field parsed from a struct/flag, or a caller passing a pointer that was never populated.

Common situations: Reading ids from optional JSON/YAML fields and forwarding them without checking presence; refactoring that drops the assignment to the id variable; CLI wrappers forwarding a missing --id flag value.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/9d8f083a44377041. Report an issue: GitHub.