JuliusBrussee/caveman · error
refusing non-regular file
Error message
refusing non-regular file
What it means
secureSQLiteFile refuses to secure anything that is not a plain regular file: if Lstat (without following symlinks) shows the path is a symlink or otherwise non-regular, it returns 'refusing non-regular file'. This is a security guard preventing the CCR store from following a planted symlink when applying permissions or writing data.
Solutions
- Replace the symlink with a real file: copy the target's contents to a regular file at that path (if intended) or remove the symlink and let Open create a fresh db
- Verify with ls -la / stat that the path is a regular file
- Never symlink CCR store files into sync folders (Dropbox/Google Drive); move the whole store directory instead
- Remove any fifo/socket/directory occupying the db path and re-run
Example fix
// before $ ln -s /mnt/sync/recovery.db /var/lib/ccr/recovery.db // after $ rm /var/lib/ccr/recovery.db $ cp /mnt/sync/recovery.db /var/lib/ccr/recovery.db && chmod 600 /var/lib/ccr/recovery.db
Defensive patterns
Strategy: validation
Validate before calling
func isRegularFile(p string) bool {
fi, err := os.Lstat(p)
return err == nil && fi.Mode().IsRegular() && fi.Mode()&os.ModeSymlink == 0
} Try / catch
err := ccr.Open(dbPath)
if err != nil && strings.Contains(err.Error(), "refusing non-regular file") {
return fmt.Errorf("%s (or a sidecar) is a symlink/special file; replace with a real file: %w", dbPath, err)
} Prevention
- Never symlink sqlite db or sidecar files
- Check with os.Lstat (not Stat) when provisioning the db path
- Exclude the store directory from scripts that create fifos/sockets
When it happens
Trigger: The sqlite path (or a -wal/-shm sidecar path) is a symlink pointing elsewhere; the 'file' is actually a directory, fifo, socket, or device node; an attacker or careless script replaced the db file with a symlink before Open.
Common situations: User symlinked the database from another location (e.g. ln -s ~/dropbox/recovery.db) to sync it; provisioning scripts created a fifo/socket at the db path; a broken deployment replaced the file with a directory.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- : database parent changed
- file changed while opening
- file changed while securing
- inspect sqlite parent ACL
- sqlite parent has no restrictive DACL
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/a1f66198d8176de5.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/store_sqlite.go:352
info, err := os.Lstat(path)
if errors.Is(err, os.ErrNotExist) && create {
createErr := createSQLiteFile(path)
if createErr == nil {
return nil
}
if !errors.Is(createErr, os.ErrExist) {
return createErr
}
info, err = os.Lstat(path)
}
if errors.Is(err, os.ErrNotExist) && !create {
return nil
}
if err != nil {
return err
}
if info.Mode()&os.ModeSymlink != 0 || !info.Mode().IsRegular() {
return fmt.Errorf("refusing non-regular file")
}
err = chmodSQLiteFile(path, info)
if errors.Is(err, os.ErrNotExist) && !create {
// The sidecar vanished while securing it — a concurrent process
// checkpointed the WAL and removed it. Nothing left to secure.
return nil
}
if err != nil {
return err
}
secured, err := os.Lstat(path)
if errors.Is(err, os.ErrNotExist) && !create {
return nil
}
if err != nil {
return err
}
if !os.SameFile(info, secured) {View on GitHub (pinned to 3ee70a1026)