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

  1. Verify the path: run `ls -l "$KEY_FILE"` as the same user the agent runs as and fix typos.
  2. Fix permissions/ownership so the agent user can read it (chmod 644, or 400 for secrets with correct owner).
  3. In Docker/K8s, confirm the secret is mounted at exactly the KEY_FILE path before the agent starts.
  4. 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

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


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