henrygd/beszel · error
failed to create smartctl directory: %w
Error message
failed to create smartctl directory: %w
What it means
Thrown by ensureEmbeddedSmartctl in agent/smart_windows.go when os.MkdirAll fails to create the temp extraction directory %TEMP%\\beszel\\smartmontools where the bundled smartctl.exe is written at runtime. It wraps the underlying OS error (e.g. permission denied, disk full, read-only volume). Until this succeeds, no embedded smartctl path is available and SMART data collection is skipped.
Source
Thrown at agent/smart_windows.go:26
"os"
"path/filepath"
"sync"
)
//go:embed smartmontools/smartctl.exe
var embeddedSmartctl []byte
var (
smartctlOnce sync.Once
smartctlPath string
smartctlErr error
)
func ensureEmbeddedSmartctl() (string, error) {
smartctlOnce.Do(func() {
destDir := filepath.Join(os.TempDir(), "beszel", "smartmontools")
if err := os.MkdirAll(destDir, 0o755); err != nil {
smartctlErr = fmt.Errorf("failed to create smartctl directory: %w", err)
return
}
destPath := filepath.Join(destDir, "smartctl.exe")
if err := os.WriteFile(destPath, embeddedSmartctl, 0o755); err != nil {
smartctlErr = fmt.Errorf("failed to write embedded smartctl: %w", err)
return
}
smartctlPath = destPath
})
return smartctlPath, smartctlErr
}
View on GitHub (pinned to b38fb7dafa)
Solutions
- Verify TMP/TEMP point to a writable directory and that the user can create folders there
- Check disk free space and file-system permissions on the temp volume
- Exclude %TEMP%\\beszel from antivirus/EDR write blocking or relocate temp via TMP env var for the agent process
- Check the wrapped %w cause: it names the exact OS reason (permission, path not found, etc.)
Example fix
// before
if err := os.MkdirAll(destDir, 0o755); err != nil {
return fmt.Errorf("failed to create smartctl directory: %w", err)
}
// after
if err := os.MkdirAll(destDir, 0o755); err != nil {
log.Warn().Err(err).Str("dir", destDir).Msg("smartctl dir creation failed; SMART disabled")
return nil // degrade gracefully instead of failing SMART collection
} Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(os.TempDir())
if err != nil || !info.IsDir() {
return fmt.Errorf("temp dir %s unusable: %w", os.TempDir(), err)
}
probe := filepath.Join(os.TempDir(), "beszel", "smartmontools")
if err := os.MkdirAll(probe, 0o755); err != nil {
return fmt.Errorf("cannot create smartctl dir: %w", err)
} Type guard
func hasWritableTempDir() bool {
f, err := os.CreateTemp("", "beszel-probe-*")
if err != nil {
return false
}
f.Close()
os.Remove(f.Name())
return true
} Try / catch
path, err := ensureEmbeddedSmartctl()
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) {
log.Printf("smartctl unavailable (%s: %v); SMART monitoring disabled", perr.Op, perr.Err)
}
return nil // degrade gracefully
} Prevention
- Ensure TMP/TEMP point to a writable, non-read-only directory
- Whitelist the agent's temp paths in antivirus/EDR policies
- Monitor disk free space on machines running the agent
- Run the agent under an account with write access to its temp dir
When it happens
Trigger: Calling agent SMART collection on Windows; smartctlOnce runs once and os.MkdirAll fails because the temp directory cannot be created or accessed.
Common situations: TMP/TEMP env vars point to a non-writable or read-only location; antivirus or endpoint protection blocks creating executables under the user temp dir; disk full; running as a service account whose temp dir is restricted.
Related errors
- failed to write embedded smartctl: %w
- failed to create temp directory: %w
- battery tag not returned
- battery capacity unknown
- data directory not found
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/89d057a24a966f0d.
Report an issue: GitHub.