JuliusBrussee/caveman · error

read current memory

Error message

read current memory: %w

What it means

Supersede failed while reading the current row of the memory to replace from SQLite. Besides sql.ErrNoRows (reported separately as "memory %s is not current"), any other query/scan failure — locked database, I/O error, corrupted schema — is wrapped here. The store fails closed: no replacement memory is written when the current version cannot be read.

Solutions

  1. Check the wrapped %w cause to distinguish I/O, lock, and schema errors (errors.Unwrap / errors.As on sqlite.Error).
  2. Verify the database file is on local writable storage and the disk is not full.
  3. Ensure no other process holds a long write lock; enable busy_timeout in the SQLite DSN.
  4. Confirm the store file was created by this version of the schema; delete or migrate a stale store file.

Example fix

// before
new, err := store.Supersede(oldID, text)
if err != nil { log.Fatal(err) }
// after
new, err := store.Supersede(oldID, text)
if err != nil {
	if strings.Contains(err.Error(), "database is locked") {
		// retry with backoff or set busy_timeout in DSN
	}
	log.Fatalf("supersede %s: %v", oldID, err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(storePath); err != nil { return err }

Try / catch

mem, err := store.Supersede(oldID, text)
if err != nil {
	cause := errors.Unwrap(err)
	log.Printf("supersede read failed: %v (cause: %v)", err, cause)
	return err
}

Prevention

When it happens

Trigger: Calling Store.Supersede(oldID, newText) when the transaction SELECT (memorySelect + ' WHERE id = ? AND valid_until IS NULL') fails for a reason other than no rows: the database file is unreadable/corrupted, the table schema is wrong, or the connection is broken mid-query.

Common situations: SQLite file on a flaky network drive or full disk; database locked by another process holding a long write transaction; running against a store file created by an older schema version that lacks expected columns; concurrent writes causing SQLITE_BUSY.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/bad788c84bda0c06. Report an issue: GitHub.

Appendix: source

Thrown at mem/store.go:222

	}
	if strings.TrimSpace(newText) == "" {
		return Memory{}, fmt.Errorf("cannot supersede with empty text")
	}
	if err := validateMemorySize(newText); err != nil {
		return Memory{}, err
	}
	tx, err := s.db.Begin()
	if err != nil {
		return Memory{}, fmt.Errorf("supersede begin: %w", err)
	}
	defer tx.Rollback()

	var old Memory
	if err := scanMemory(tx.QueryRow(memorySelect+` WHERE id = ? AND valid_until IS NULL`, oldID), &old); err != nil {
		if err == sql.ErrNoRows {
			return Memory{}, fmt.Errorf("memory %s is not current", oldID)
		}
		return Memory{}, fmt.Errorf("read current memory: %w", err)
	}
	if old.Text == newText {
		return Memory{}, fmt.Errorf("replacement text is identical to current memory")
	}
	newID := memID(newText)
	var exists int
	if err := tx.QueryRow(`SELECT COUNT(*) FROM memories WHERE id = ?`, newID).Scan(&exists); err != nil {
		return Memory{}, fmt.Errorf("check replacement memory: %w", err)
	}
	if exists > 0 {
		return Memory{}, fmt.Errorf("replacement memory %s already exists", newID)
	}
	now := time.Now().UTC().Format(time.RFC3339Nano)
	if _, err := tx.Exec(
		`INSERT INTO memories
		   (id, text, created_at, valid_from, supersedes)
		 VALUES (?, ?, ?, ?, ?)`,
		newID, newText, now, now, oldID,

View on GitHub (pinned to 3ee70a1026)