henrygd/beszel · error

chmod: %w

Error message

chmod: %w

What it means

After a successful download, downloadFile chmods the temp file to 0o755 so it can be executed and moved into place. If os.Chmod fails, the error is wrapped as `chmod: %w` and the temp file is removed.

Source

Thrown at agent/tools/fetchsmartctl/main.go:116

	}
	if err := f.Close(); err != nil {
		os.Remove(tmp)
		return fmt.Errorf("close tmp: %w", err)
	}

	if hasher != nil && shaHex != "" {
		cleanSha := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(shaHex), " ", ""))
		got := strings.ToLower(hex.EncodeToString(hasher.Sum(nil)))
		if got != cleanSha {
			os.Remove(tmp)
			return fmt.Errorf("hash mismatch: got %s want %s", got, cleanSha)
		}
	}

	// Make executable and move into place
	if err := os.Chmod(tmp, 0o755); err != nil {
		os.Remove(tmp)
		return fmt.Errorf("chmod: %w", err)
	}
	if err := os.Rename(tmp, dest); err != nil {
		os.Remove(tmp)
		return fmt.Errorf("rename: %w", err)
	}

	fmt.Println("smartctl.exe downloaded to", dest)
	return nil
}

func fatalf(format string, a ...any) {
	fmt.Fprintf(os.Stderr, format+"\n", a...)
	os.Exit(1)
}

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Point TMPDIR (or the destination) at a filesystem supporting POSIX permissions (e.g. Linux ext4 /tmp).
  2. Check mount options of the target filesystem; remount without restrictive fmask/dmask so chmod 0755 is permitted.
  3. Inspect the wrapped underlying error (%w) for the real cause (EACCES, EPERM, ENOENT) and address it directly.
  4. On Windows, chmod is largely unsupported — use a Windows-appropriate install path or skip the chmod.

Example fix

// before
if err := os.Chmod(tmp, 0o755); err != nil {
	return fmt.Errorf("chmod: %w", err)
}
// after
if runtime.GOOS != "windows" {
	if err := os.Chmod(tmp, 0o755); err != nil {
		return fmt.Errorf("chmod: %w", err)
	}
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check the temp filesystem supports chmod before downloading
if fi, err := os.Stat(os.TempDir()); err == nil {
	_ = fi // on Windows or vfat mounts, plan to skip chmod
}

Try / catch

if err := downloadFile(url, dest, sha); err != nil {
	if strings.HasPrefix(err.Error(), "chmod:") {
		log.Printf("chmod failed (filesystem may not support perms): %v", err)
	} else {
		return err
	}
}

Prevention

When it happens

Trigger: os.Chmod(tmp, 0o755) returns an error: the temp file sits on a filesystem that rejects permission changes (FAT32/exFAT mounts, some network shares, Windows filesystems), or the file was removed between creation and chmod.

Common situations: Running the downloader on a Windows filesystem or a USB/network share lacking POSIX perms; TMPDIR redirected to a restrictive mount; antivirus deleting the temp file mid-run.

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


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/5277c32f6cd5da61. Report an issue: GitHub.