henrygd/beszel · error
failed to read key file: %w
Error message
failed to read key file: %w
What it means
When KEY_FILE is set, loadPublicKeys reads that file with os.ReadFile and parses its contents as SSH public keys. Any file-read failure (missing, permission denied, is-a-directory) is wrapped with %w so the agent fails fast with the underlying reason.
Source
Thrown at internal/cmd/agent/agent.go:132
// Try command line flag first
if opts.key != "" {
return agent.ParseKeys(opts.key)
}
// Try environment variable
if key, ok := utils.GetEnv("KEY"); ok && key != "" {
return agent.ParseKeys(key)
}
// Try key file
keyFile, ok := utils.GetEnv("KEY_FILE")
if !ok {
return nil, fmt.Errorf("no key provided: must set -key flag, KEY env var, or KEY_FILE env var. Use 'beszel-agent help' for usage")
}
pubKey, err := os.ReadFile(keyFile)
if err != nil {
return nil, fmt.Errorf("failed to read key file: %w", err)
}
return agent.ParseKeys(string(pubKey))
}
func (opts *cmdOptions) getAddress() string {
return agent.GetAddress(opts.listen)
}
// handleFingerprint handles the "fingerprint" command with subcommands "view" and "reset".
func handleFingerprint() {
subCmd := ""
if len(os.Args) > 2 {
subCmd = os.Args[2]
}
switch subCmd {
case "", "view":
dataDir, _ := agent.GetDataDir()View on GitHub (pinned to b38fb7dafa)
Solutions
- Verify the path: run `ls -l "$KEY_FILE"` as the same user the agent runs as and fix typos.
- Fix permissions/ownership so the agent user can read it (chmod 644, or 400 for secrets with correct owner).
- In Docker/K8s, confirm the secret is mounted at exactly the KEY_FILE path before the agent starts.
- If SELinux denies the read, restore labels (restorecon) or adjust policy.
Example fix
# before KEY_FILE=/etc/beszel/key # missing or root-only # after sudo install -m 0444 -o beszel /srv/secrets/beszel_pub /etc/beszel/key KEY_FILE=/etc/beszel/key
Defensive patterns
Strategy: validation
Validate before calling
// pre-check readability before launching the agent
if kf := os.Getenv("KEY_FILE"); kf != "" {
if f, err := os.Open(kf); err != nil {
log.Fatalf("KEY_FILE %q unreadable: %v", kf, err)
} else {
f.Close()
}
} Try / catch
keys, err := loadPublicKeys(opts)
if err != nil {
if strings.HasPrefix(err.Error(), "failed to read key file") {
log.Printf("check KEY_FILE path, permissions, and secret mounts: %v", err)
}
log.Fatal(err)
} Prevention
- Verify KEY_FILE path and permissions as the service user before deploy.
- In K8s/Docker, mount secrets at the exact KEY_FILE path.
- Use install -m 0444 (or 0400) with correct owner for key files.
- Check SELinux/AppArmor denials when reads fail mysteriously.
When it happens
Trigger: KEY_FILE points to a nonexistent path, an unreadable file (permissions/ownership), a directory, or a secret mount not present at container start (Docker/K8s secret path mismatch, bind mount not propagated).
Common situations: Secret mounted at a different path than KEY_FILE; file owned by root with 600 perms while the agent runs unprivileged; path typo; SELinux/AppArmor blocking the read.
Related errors
- no key provided: must set -key flag, KEY env var, or KEY_FIL
- data directory not found
- SSH disabled
- ${resp.Error}
- timeout creating session
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/914072961b7cc296.
Report an issue: GitHub.