JuliusBrussee/caveman · error
inspect sqlite parent
Error message
inspect sqlite parent %q: %w
What it means
PrepareSQLitePathCanonical resolves the parent directory of the SQLite database path via filepath.EvalSymlinks, and this error wraps any failure from that resolution. It means the library could not canonicalize the parent directory (e.g. it does not exist, is inaccessible, or a symlink loop was found) before opening the CCR SQLite store, so it refuses to proceed rather than opening an unsafe path.
Solutions
- Verify the parent directory of the sqlite path exists; create it with os.MkdirAll before calling Open
- Check for broken symlinks in the path (ls -l / readlink -f) and repair or remove them
- Ensure the process has execute/traverse permission on every component of the parent path
- Fix the configured database path in your engine/store configuration
- Run as a user with access to the directory; on Windows confirm the path is a valid NTFS path without a symlink loop
Example fix
// before
store, err := ccr.Open("/var/lib/ccr/cache/recovery.db") // parent missing
// after
if err := os.MkdirAll("/var/lib/ccr/cache", 0o700); err != nil { log.Fatal(err) }
store, err := ccr.Open("/var/lib/ccr/cache/recovery.db") Defensive patterns
Strategy: validation
Validate before calling
func parentExists(dbPath string) error {
parent := filepath.Dir(dbPath)
if _, err := filepath.EvalSymlinks(parent); err != nil {
return fmt.Errorf("cannot resolve parent %q: %w", parent, err)
}
return nil
} Try / catch
path, err := ccr.PrepareSQLitePath(dbPath)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) { os.MkdirAll(filepath.Dir(dbPath), 0o700) }
return err
} Prevention
- Always os.MkdirAll(filepath.Dir(dbPath), 0o700) before Open
- Avoid symlinks in the sqlite store path
- Validate configured paths at startup with a fail-fast check
- Ensure the run-as user can traverse the full path
When it happens
Trigger: Calling ccr.Open/PrepareSQLitePath with a database path whose parent directory does not exist on disk; the parent path contains a broken symlink; the parent symlink chain forms a loop; or the process lacks permission to traverse a symlinked parent on any platform including Windows.
Common situations: A config file points at a data directory that was deleted or never created (e.g. ~/.caveman/ccr removed by a cleanup tool); a docker volume or mount point not yet mounted when the engine starts; running on Windows where EvalSymlinks fails for certain paths; typo in the directory portion of the configured db path.
Related errors
- inspect sqlite parent ACL
- sqlite parent has no restrictive DACL
- sqlite parent has no security descriptor
- sqlite parent is group/world writable
- sqlite parent must be a directory
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/004ad3d1e7c7fbed.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/store_sqlite.go:298
func PrepareSQLitePathCanonical(path string) (string, error) {
if path == ":memory:" {
return path, nil
}
if strings.TrimSpace(path) == "" {
return "", fmt.Errorf("ccr sqlite path is required")
}
parent := filepath.Dir(path)
absoluteParent, err := filepath.Abs(parent)
if err != nil {
return "", fmt.Errorf("resolve sqlite parent %q: %w", parent, err)
}
resolvedParent, err := filepath.EvalSymlinks(absoluteParent)
if err != nil {
return "", fmt.Errorf("resolve sqlite parent %q: %w", parent, err)
}
parentInfo, err := os.Stat(resolvedParent)
if err != nil {
return "", fmt.Errorf("inspect sqlite parent %q: %w", resolvedParent, err)
}
if !parentInfo.IsDir() {
return "", fmt.Errorf("sqlite parent %q must be a directory", resolvedParent)
}
if err := validateSQLiteParentSecurity(resolvedParent, parentInfo); err != nil {
return "", err
}
canonicalPath := filepath.Join(resolvedParent, filepath.Base(path))
if err := secureSQLiteFile(canonicalPath, true); err != nil {
return "", fmt.Errorf("secure sqlite %q: %w", canonicalPath, err)
}
for _, suffix := range []string{"-wal", "-shm"} {
if err := secureSQLiteFile(canonicalPath+suffix, false); err != nil {
return "", fmt.Errorf("secure sqlite sidecar %q: %w", canonicalPath+suffix, err)
}
}
return canonicalPath, nil
}View on GitHub (pinned to 3ee70a1026)