JuliusBrussee/caveman · error
inspect sqlite parent ACL
Error message
inspect sqlite parent ACL %q: %w
What it means
On Windows, engine/ccr validates that the SQLite database's parent directory has a restrictive DACL so other local users cannot replace the database file. If GetNamedSecurityInfo fails while reading the directory's DACL, the failure is wrapped as 'inspect sqlite parent ACL %q: %w' so the caller sees both the path and the underlying Windows API error.
Solutions
- Read the wrapped Win32 error: if it is file-not-found, ensure the parent directory exists before opening the store; if access-denied, grant the process READ_CONTROL on the directory
- Move the database onto a local NTFS volume owned by the running user instead of a network share or FAT-formatted drive
- Pre-create the parent directory with restrictive ACLs (icacls <dir> /inheritance:r /grant:r "%USERNAME%":F) before first store open
Example fix
// before store, _ := engine.OpenCCRStore(`\\server\share\ccr\db.sqlite`) // no ACLs on share // after os.MkdirAll(`C:\ProgramData\myapp\ccr`, 0o700) store, _ := engine.OpenCCRStore(`C:\ProgramData\myapp\ccr\db.sqlite`)
Defensive patterns
Strategy: try-catch
Validate before calling
if fi, err := os.Stat(parentDir); err != nil || !fi.IsDir() {
return fmt.Errorf("parent %s must be a local directory", parentDir)
} Try / catch
store, err := engine.OpenCCRStore(path)
if err != nil && strings.Contains(err.Error(), "inspect sqlite parent ACL") {
// wrapped Win32 error: check for not-found (create dir) or access-denied (grant READ_CONTROL),
// or relocate to local NTFS storage
} Prevention
- Store databases on local NTFS volumes, not network shares or FAT drives
- Ensure the parent directory exists and the process can read its security info
- Pre-create data directories with explicit restrictive ACLs (icacls)
When it happens
Trigger: Calling validateSQLiteParentSecurity on Windows when windows.GetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION) fails — e.g. the path does not exist, is a network/UNC location without retrievable security info, or the caller lacks READ_CONTROL on the directory.
Common situations: Database placed on a network share or mapped drive where ACLs are unavailable; path deleted or on an unavailable volume at store-open time; running from a context without permission to read the directory's security descriptor; FAT/exFAT filesystems with no ACL support.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- sqlite parent has no restrictive DACL
- sqlite parent has no security descriptor
- sqlite parent grants broad Windows write access
- sqlite parent is group/world writable
- : database parent changed
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/9d467bf6b5566bd6.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/sqlite_parent_security_windows.go:20
package ccr
import (
"fmt"
"os"
"unsafe"
"golang.org/x/sys/windows"
)
func validateSQLiteParentSecurity(path string, _ os.FileInfo) error {
descriptor, err := windows.GetNamedSecurityInfo(
path,
windows.SE_FILE_OBJECT,
windows.DACL_SECURITY_INFORMATION,
)
if err != nil {
return fmt.Errorf("inspect sqlite parent ACL %q: %w", path, err)
}
if descriptor == nil {
return fmt.Errorf("sqlite parent %q has no security descriptor", path)
}
dacl, _, err := descriptor.DACL()
if err != nil || dacl == nil {
return fmt.Errorf("sqlite parent %q has no restrictive DACL", path)
}
broad, err := windowsACLGrantsBroadWrite(dacl)
if err != nil {
return fmt.Errorf("inspect sqlite parent ACL %q: %w", path, err)
}
if broad {
return fmt.Errorf("sqlite parent %q grants broad Windows write access", path)
}
return nil
}
View on GitHub (pinned to 3ee70a1026)