vxcontrol/pentagi · critical
failed to create resources directory: %w
Error message
failed to create resources directory: %w
What it means
EnsureResourcesDir creates the resources blob-storage directory (<dataDir>/resources, mode 0755) via os.MkdirAll and wraps any OS error with this message. Callers (CommitBlob, promoteToResources, UploadResources) invoke it before writing blob files, so failure here means the storage root cannot be prepared and the resource write must abort.
Source
Thrown at backend/pkg/resources/resources.go:66
// ResourcesDir returns the absolute path to the flat blob storage directory.
func ResourcesDir(dataDir string) string {
return filepath.Join(dataDir, ResourcesDirName)
}
// BlobPath returns the absolute path to the .blob file for a given MD5 hash.
func BlobPath(dataDir, hash string) string {
cleanHash := strings.ToLower(strings.TrimSpace(hash))
if !IsValidBlobHash(cleanHash) {
return filepath.Join(ResourcesDir(dataDir), invalidBlobHashFileName)
}
return filepath.Join(ResourcesDir(dataDir), cleanHash+".blob")
}
// EnsureResourcesDir creates the resources storage directory if it does not exist.
func EnsureResourcesDir(dataDir string) error {
if err := os.MkdirAll(ResourcesDir(dataDir), 0755); err != nil {
return fmt.Errorf("failed to create resources directory: %w", err)
}
return nil
}
// ComputeFileMD5 reads r to EOF and returns the lowercase hex MD5 digest.
func ComputeFileMD5(r io.Reader) (string, error) {
h := md5.New()
if _, err := io.Copy(h, r); err != nil {
return "", fmt.Errorf("failed to compute MD5: %w", err)
}
return hex.EncodeToString(h.Sum(nil)), nil
}
// IsValidBlobHash reports whether hash is a hex-encoded MD5 digest.
func IsValidBlobHash(hash string) bool {
if len(hash) != md5.Size*2 {
return false
}View on GitHub (pinned to ea665308ba)
Solutions
- Check the wrapped %w cause and errno to identify the OS-level reason.
- Verify the configured data dir (DATA_DIR / config value) points to a writable directory, not a file: ls -ld <dataDir> and check it is a directory.
- Fix permissions/ownership: chown or chmod the data directory (or its parent) for the user running the process.
- If running in Docker, ensure the data volume is not mounted read-only (remove :ro from docker-compose).
- Free disk space / check mount health (df -h, dmesg) if the errno is ENOSPC or EIO.
Example fix
// before: data dir is a file, so MkdirAll fails with ENOTDIR $ touch /var/lib/pentagi/data DATA_DIR=/var/lib/pentagi/data // after: data dir is a real, writable directory $ rm /var/lib/pentagi/data && mkdir -p /var/lib/pentagi/data && chown pentagi:pentagi /var/lib/pentagi/data DATA_DIR=/var/lib/pentagi/data
Defensive patterns
Strategy: try-catch
Validate before calling
// check writability before attempting blob writes
dir := resources.ResourcesDir(dataDir)
if fi, err := os.Stat(dir); err == nil && !fi.IsDir() {
return fmt.Errorf("data dir path %s exists but is not a directory", dir)
}
if err := resources.EnsureResourcesDir(dataDir); err != nil {
return fmt.Errorf("storage not writable: %w", err)
} Type guard
func resourcesDirReady(dataDir string) bool {
fi, err := os.Stat(resources.ResourcesDir(dataDir))
return err == nil && fi.IsDir()
} Try / catch
if err := resources.EnsureResourcesDir(cfg.DataDir); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
log.Fatalf("cannot create resources dir %s: permission denied — fix DATA_DIR ownership/mount", cfg.DataDir)
}
return fmt.Errorf("failed to create resources directory: %w", err)
} Prevention
- Validate DATA_DIR at startup (exists, is a directory, writable via a probe file) before serving traffic
- Run the process with a user that owns or has write access to the data directory
- In Docker, mount the data volume without :ro and set correct ownership on the host path
- Check disk space monitoring/alerting on the data volume
- Wrap and log errors.Unwrap to surface the fs.PathError errno in operations runbooks
When it happens
Trigger: os.MkdirAll(ResourcesDir(dataDir), 0755) returns a non-nil error at resources.go:65 — the path's parent exists but is a file (ENOTDIR), a permissions problem (EACCES/EACCES on mkdir), a read-only filesystem (EROFS), or disk/device errors. dataDir comes from configuration.
Common situations: DATA_DIR env var misconfigured to a path that is a regular file or does not exist with unwritable parents; running the container/binary as a non-root user against a root-owned data directory; read-only container volume mount on the data dir; disk full or I/O errors on the host.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- token validation disabled with default salt
- Internal
- failed to switch provider: %w
- failed to stop flow %d: %w
- knowledge: embedding provider is not configured
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/3c3e3db2b403ec8a.
Report an issue: GitHub.