JuliusBrussee/caveman · warning
cannot remember empty text
Error message
cannot remember empty text
What it means
Remember() rejects text that is empty or consists only of whitespace, because storing a blank memory would pollute the store and be unusable in recall. The check happens first, before any id computation or database write.
Solutions
- Trim and check the text before calling Remember; skip the call entirely for blank input.
- Fix the upstream source so the intended text is actually passed (unset variable, wrong flag).
- For CLI use, pass the memory text as a quoted argument.
- If blank input is legitimate in your flow, treat the error as a no-op rather than a failure.
Example fix
// before
text := os.Getenv("MEMORY")
mem, err := store.Remember(text)
// after
text := strings.TrimSpace(os.Getenv("MEMORY"))
if text == "" {
return nil // nothing to remember
}
mem, err := store.Remember(text) Defensive patterns
Strategy: validation
Validate before calling
// Go
func canRemember(text string) bool { return strings.TrimSpace(text) != "" } Try / catch
if strings.TrimSpace(text) == "" { return nil }
m, err := store.Remember(text)
if err != nil { return fmt.Errorf("remember: %w", err) } Prevention
- Trim and non-empty-check all text before Remember
- Validate CLI/env inputs before they reach the store
- Treat blank input as a no-op in pipelines
- Quote shell arguments so empty expansions are caught early
When it happens
Trigger: Calling Store.Remember(""), Remember(" "), Remember("\n\t"), or passing unvalidated user/CLI input whose text field ended up blank (e.g. cmdRemember with an empty argument or a dropped flag value).
Common situations: CLI invocation like `mem remember ""`, shell variable expansion where $MEMORY is unset, or upstream pipelines that strip text before calling Remember.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- cannot supersede with empty text
- caveman agent: file path is required
- : memory is bytes, over the -byte cap
- apiKey, baseURL, and agent are required
- arm must be or
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/74d3a882244eb342.
Report an issue: GitHub.
Appendix: source
Thrown at mem/store.go:168
// Memory is one stored memory.
type Memory struct {
ID string `json:"id"`
Text string `json:"text"`
CreatedAt string `json:"created_at"`
ValidFrom string `json:"valid_from"`
ValidUntil *string `json:"valid_until,omitempty"`
Supersedes string `json:"supersedes,omitempty"`
SupersededBy string `json:"superseded_by,omitempty"`
}
// Remember stores text durably and returns it with a content-addressed id.
// Remembering identical current text twice is idempotent (same id, stored once).
// Text that exists only as an expired historical version is rejected: returning
// that row as success would claim it was remembered while Recall still hides it.
// The raw text is written before any other work, so a memory is never lost.
func (s *Store) Remember(text string) (Memory, error) {
if strings.TrimSpace(text) == "" {
return Memory{}, fmt.Errorf("cannot remember empty text")
}
if err := validateMemorySize(text); err != nil {
return Memory{}, err
}
id := memID(text)
created := time.Now().UTC().Format(time.RFC3339Nano)
// INSERT OR IGNORE keeps the original created_at on a repeat remember.
// RetryOnBusy: under a fan-out of cavemem processes, a queued writer can
// outlast a single busy_timeout (Windows file locking is the slowest case).
if err := ccr.RetryOnBusy(func() error {
_, e := s.db.Exec(
`INSERT OR IGNORE INTO memories (id, text, created_at, valid_from) VALUES (?, ?, ?, ?)`,
id, text, created, created,
)
return e
}); err != nil {
return Memory{}, fmt.Errorf("store memory: %w", err)
}View on GitHub (pinned to 3ee70a1026)