netbirdio/netbird · error
failed to generate root key: %w
Error message
failed to generate root key: %w
What it means
Umbrella wrap around handleGenerateRootKey (rootkey.go:31). It covers three distinct inner failures, each self-identifying in the %w chain: 'generate root key: ...' from reposign.GenerateRootKey (entropy or marshal failure), 'write private key file (path): ...' and 'write public key file (path): ...' from the two os.WriteFile calls with 0600 permissions. The dominant real-world cause is one of the writes failing on a missing directory or insufficient permissions.
Source
Thrown at client/cmd/signer/rootkey.go:32
privKeyFile string
pubKeyFile string
rootExpiration time.Duration
)
var createRootKeyCmd = &cobra.Command{
Use: "create-root-key",
Short: "Create a new root key pair",
Long: `Create a new root key pair and specify an expiration time for it.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
// Validate expiration
if rootExpiration <= 0 {
return fmt.Errorf("--expiration must be a positive duration (e.g., 720h, 365d, 8760h)")
}
// Run main logic
if err := handleGenerateRootKey(cmd, privKeyFile, pubKeyFile, rootExpiration); err != nil {
return fmt.Errorf("failed to generate root key: %w", err)
}
return nil
},
}
func init() {
rootCmd.AddCommand(createRootKeyCmd)
createRootKeyCmd.Flags().StringVar(&privKeyFile, "priv-key-file", "", "Path to output private key file")
createRootKeyCmd.Flags().StringVar(&pubKeyFile, "pub-key-file", "", "Path to output public key file")
createRootKeyCmd.Flags().DurationVar(&rootExpiration, "expiration", 0, "Expiration time for the root key (e.g., 720h,)")
if err := createRootKeyCmd.MarkFlagRequired("priv-key-file"); err != nil {
panic(err)
}
if err := createRootKeyCmd.MarkFlagRequired("pub-key-file"); err != nil {
panic(err)
}
if err := createRootKeyCmd.MarkFlagRequired("expiration"); err != nil {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Identify the failing step from the inner message (generate vs write private vs write public)
- mkdir -p the parent directories of both --priv-key-file and --pub-key-file
- Fix ownership of pre-existing target files or choose fresh paths
- If the inner error is 'generate root key', see the entropy guidance for error 359
Example fix
# before signer create-root-key --priv-key-file /etc/netbird/keys/root.pem --pub-key-file /etc/netbird/keys/root-public.pem --expiration 8760h # error: failed to generate root key: write private key file (/etc/netbird/keys/root.pem): open ...: no such file or directory # after mkdir -p /etc/netbird/keys signer create-root-key --priv-key-file /etc/netbird/keys/root.pem --pub-key-file /etc/netbird/keys/root-public.pem --expiration 8760h
Defensive patterns
Strategy: validation
Validate before calling
func preflightKeygen(priv, pub string) error {
for _, p := range []string{priv, pub} {
dir := filepath.Dir(p)
if _, err := os.Stat(dir); err != nil {
return fmt.Errorf("output dir %s: %w", dir, err)
}
if err := ensureWritableDir(p); err != nil {
return err
}
}
return nil
}
// before create-root-key:
// err := preflightKeygen(privKeyFile, pubKeyFile) Prevention
- mkdir -p both output directories in provisioning scripts
- Disambiguate failures via the inner error: write private/public vs generate
- Choose fresh output paths per rotation instead of reusing root-owned files
When it happens
Trigger: create-root-key with an output path in a directory that does not exist or is not writable; an existing file at the target owned by another user; in rare cases a system where the entropy source is unavailable so key generation itself fails.
Common situations: First-run setup on a new signing host where the key directory was never created; running as non-root against /etc paths; leftover root-owned key files from a previous attempt under a different user.
Related errors
- failed to read public root key file: %w
- failed to create artifact key: %w
- at least one --artifact-pub-key-file must be provided
- read root private key file: %w
- write private key file (%s): %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/234dacd0890a9400.
Report an issue: GitHub.