vxcontrol/pentagi · error
failed to delete blob %s: %w
Error message
failed to delete blob %s: %w
What it means
DeleteBlob (resources.go:124) removes the .blob file for a hash after validating it. If os.Remove fails for any reason other than 'file does not exist' (which is silently treated as success), the error 'failed to delete blob %s: %w' wraps the filesystem error. So this surfaces real removal problems: permissions, directory issues, or the path being a non-empty directory.
Source
Thrown at backend/pkg/resources/resources.go:124
_, err := os.Lstat(BlobPath(dataDir, hash))
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// DeleteBlob removes the .blob file for hash. It is safe to call if the file
// does not exist (returns nil in that case).
func DeleteBlob(dataDir, hash string) error {
if err := validateBlobHash(hash); err != nil {
return err
}
err := os.Remove(BlobPath(dataDir, hash))
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete blob %s: %w", hash, err)
}
return nil
}
// SanitizeResourcePath normalises a client-supplied virtual path and ensures it
// is safe to use:
// - trims whitespace
// - converts backslashes to forward slashes
// - cleans the path (removes .., double slashes, etc.)
// - rejects absolute paths, dot-only components, and paths that exceed MaxPathLength
// - returns an error for the empty path
func SanitizeResourcePath(p string) (string, error) {
trimmed := strings.TrimSpace(p)
if trimmed == "" {
return "", fmt.Errorf("path must not be empty")
}
if len(trimmed) > MaxPathLength {
return "", fmt.Errorf("path exceeds maximum allowed length of %d characters", MaxPathLength)View on GitHub (pinned to ea665308ba)
Solutions
- Check the wrapped cause (errors.Unwrap / os.RemoveAll behavior) and the path from BlobPath(dataDir, hash)
- Verify write permission on the blob directory for the process user (ls -ld dataDir)
- Confirm the volume is not mounted read-only (mount | grep, kubectl describe)
- If the entry is a directory or corrupted, remove it manually or with os.RemoveAll after verifying it is safe
Example fix
// before
if err := resources.DeleteBlob(dataDir, hash); err != nil { return err }
// after
if err := resources.DeleteBlob(dataDir, hash); err != nil {
var perr *fs.PathError
if errors.As(err, &perr) && (errors.Is(perr, os.ErrPermission) || errors.Is(perr, syscall.EACCES)) {
log.Warn("skipping blob delete, permission denied", "hash", hash)
return nil // or escalate
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
if !resources.IsValidBlobHash(hash) { return fmt.Errorf("invalid hash %q", hash) }
if info, err := os.Stat(resources.BlobPath(dataDir, hash)); err == nil && info.IsDir() {
return fmt.Errorf("blob path is a directory")
} Type guard
func isPermissionErr(err error) bool {
var perr *fs.PathError
return errors.As(err, &perr) && errors.Is(perr, os.ErrPermission)
} Try / catch
if err := resources.DeleteBlob(dataDir, hash); err != nil {
if isPermissionErr(err) { log.Warn("no permission to delete blob", "hash", hash); return nil }
return fmt.Errorf("blob delete failed: %w", err)
} Prevention
- Run the service with a user that owns or has write access to the blob directory
- Ensure blob volumes are mounted read-write (verify in docker-compose/k8s specs)
- Treat os.ErrNotExist as success — DeleteBlob already does — so only handle real failures
- Check disk/volume health in cleanup workers and log the wrapped PathError for diagnosis
When it happens
Trigger: os.Remove returns EACCES/EPERM (no write permission on the blob directory), the blob path exists as a directory, the filesystem is read-only or full (rare for unlink), or the dataDir points to the wrong location holding a similarly-named directory.
Common situations: Running the process as a non-root user after blobs were created by another user; mounting the blob volume read-only; orphan-blob cleanup workers (deleteOrphanBlobsIfUnreferenced, cleanupOrphanBlobs) hitting blobs locked down by backup tooling; k8s volumes remounted read-only.
Related errors
- failed to create tmp directory: %w
- failed to set temporary upload file permissions: %w
- failed to create file '%s': %w
- failed to create temp directory: %w
- failed to create temp file: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/ed97947c5cdaa66d.
Report an issue: GitHub.