henrygd/beszel · error
failed to create update data directory: %w
Error message
failed to create update data directory: %w
What it means
Before staging the download, update() creates Config.DataDir (defaulting to os.TempDir()) recursively with os.MkdirAll. If that fails — permission denied, read-only filesystem, path is a file, etc. — the error is wrapped with this message. No download happens until a writable data directory exists.
Source
Thrown at internal/ghupdate/ghupdate.go:143
return false, err
}
currentVersion := semver.MustParse(strings.TrimPrefix(p.currentVersion, "v"))
newVersion := semver.MustParse(strings.TrimPrefix(latest.Tag, "v"))
if newVersion.LTE(currentVersion) {
ColorPrintf(ColorGreen, "You already have the latest version %s.", p.currentVersion)
return false, nil
}
suffix := archiveSuffix(p.config.ArchiveExecutable, runtime.GOOS, runtime.GOARCH, buildGOARM)
asset, err := latest.findAssetBySuffix(suffix)
if err != nil {
return false, err
}
if err := os.MkdirAll(p.config.DataDir, 0755); err != nil {
return false, fmt.Errorf("failed to create update data directory: %w", err)
}
releaseDir, err := os.MkdirTemp(p.config.DataDir, ".beszel_update-")
if err != nil {
return false, fmt.Errorf("failed to create update directory: %w", err)
}
defer os.RemoveAll(releaseDir)
ColorPrintf(ColorYellow, "Downloading %s...", asset.Name)
// download the release asset
assetPath, err := archivePath(releaseDir, asset.Name)
if err != nil {
return false, err
}
if err := downloadFile(p.config.Context, p.config.HttpClient, asset.DownloadUrl, assetPath, p.config.UseMirror); err != nil {
return false, err
}
ColorPrint(ColorYellow, "Verifying checksum...")View on GitHub (pinned to b38fb7dafa)
Solutions
- Create the directory manually with correct ownership: `sudo mkdir -p <DataDir> && sudo chown <user> <DataDir>`.
- Point Config.DataDir at a writable location for the user running the process (e.g. /var/lib/beszel owned by the service user).
- Check that the path isn't an existing regular file and the filesystem isn't mounted read-only (`mount | grep <path>`).
- Review SELinux/AppArmor audit logs if permissions look correct but creation still fails.
Example fix
// before
Update(ghupdate.Config{DataDir: "/root/.beszel"}) // running as non-root
// after
Update(ghupdate.Config{DataDir: "/home/deploy/.beszel"}) Defensive patterns
Strategy: validation
Validate before calling
if err := os.MkdirAll(cfg.DataDir, 0755); err != nil {
return fmt.Errorf("pre-flight: cannot create DataDir %q: %w", cfg.DataDir, err)
}
if fi, err := os.Stat(cfg.DataDir); err != nil || !fi.IsDir() {
return errors.New("DataDir path exists but is not a directory")
} Try / catch
updated, err := ghupdate.Update(cfg)
if err != nil && strings.Contains(err.Error(), "failed to create update data directory") {
log.Printf("DataDir %q is not creatable (%v); fix ownership/mount or choose a writable path", cfg.DataDir, err)
} Prevention
- Pre-create DataDir at deploy time with the service user as owner.
- Never point DataDir at a read-only mount, container image layer, or a regular file path.
- Verify writability in your service's health/startup checks.
When it happens
Trigger: ghupdate.Update -> update when os.MkdirAll(DataDir, 0755) fails: DataDir points at a path the running user cannot create, an existing file occupies the path, or the filesystem is read-only.
Common situations: Running the agent as an unprivileged user while DataDir is owned by root; DataDir set to a path inside a read-only container layer; a regular file accidentally exists at the DataDir path; SELinux/AppArmor denial.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- data directory not found
- chmod: %w
- failed to read key file: %w
- failed to open release for checksum verification: %w
- failed to create update directory: %w
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/2319f2ea6e77965e.
Report an issue: GitHub.