netbirdio/netbird · error
read root private key file: %w
Error message
read root private key file: %w
What it means
os.ReadFile on the --root-private-key-file path failed inside handleCreateArtifactKey, before any cryptographic work. The wrapped error is a standard *fs.PathError: 'no such file or directory', 'permission denied', or 'is a directory'.
Source
Thrown at client/cmd/signer/artifactkey.go:102
bundlePubKeysCmd.Flags().StringVar(&bundlePubKeysFile, "bundle-pub-key-file", "", "Path where the public keys will be saved")
if err := bundlePubKeysCmd.MarkFlagRequired("root-private-key-file"); err != nil {
panic(fmt.Errorf("mark root-private-key-file as required: %w", err))
}
if err := bundlePubKeysCmd.MarkFlagRequired("artifact-pub-key-file"); err != nil {
panic(fmt.Errorf("mark artifact-pub-key-file as required: %w", err))
}
if err := bundlePubKeysCmd.MarkFlagRequired("bundle-pub-key-file"); err != nil {
panic(fmt.Errorf("mark bundle-pub-key-file as required: %w", err))
}
}
func handleCreateArtifactKey(cmd *cobra.Command, rootPrivKeyFile, artifactPrivKeyFile, artifactPubKeyFile string, expiration time.Duration) error {
cmd.Println("Creating new artifact signing key...")
privKeyPEM, err := os.ReadFile(rootPrivKeyFile)
if err != nil {
return fmt.Errorf("read root private key file: %w", err)
}
privateRootKey, err := reposign.ParseRootKey(privKeyPEM)
if err != nil {
return fmt.Errorf("failed to parse private root key: %w", err)
}
artifactKey, privPEM, pubPEM, signature, err := reposign.GenerateArtifactKey(privateRootKey, expiration)
if err != nil {
return fmt.Errorf("generate artifact key: %w", err)
}
if err := os.WriteFile(artifactPrivKeyFile, privPEM, 0o600); err != nil {
return fmt.Errorf("write private key file (%s): %w", artifactPrivKeyFile, err)
}
if err := os.WriteFile(artifactPubKeyFile, pubPEM, 0o600); err != nil {
return fmt.Errorf("write public key file (%s): %w", artifactPubKeyFile, err)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Check the exact path and rerun with an absolute path to rule out working-directory issues
- Confirm the file exists and is readable (ls -l, or run as the owning user)
- If no root key exists yet, generate one with the create-root-key command first
Example fix
// before create-artifact-key --root-private-key-file root.key ... // after create-artifact-key --root-private-key-file /etc/netbird/signing/root.key ...
Defensive patterns
Strategy: validation
Validate before calling
keyPath := "/etc/netbird/signing/root.key"
if _, err := os.Stat(keyPath); err != nil {
log.Fatalf("root key not available at %s: %v", keyPath, err)
}
// then invoke create-artifact-key with keyPath Prevention
- Store root key at a fixed absolute path referenced by the pipeline
- Use os.Stat pre-checks in wrapper scripts to give clearer diagnostics
- Never rename or move key files after generation
When it happens
Trigger: create-artifact-key invoked with a --root-private-key-file path that does not exist, is a directory, or is not readable by the current user (e.g. root-owned 0600 file read as a normal user).
Common situations: Typo in the path; running from a different working directory with a relative path; the root key was never generated or was moved; file permissions were tightened after generation.
Related errors
- failed to create artifact key: %w
- write signature file (%s): %w
- read public key file: %w
- read private key file: %w
- --expiration must be a positive duration (e.g., 720h, 365d,
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/19ed447cf2b1fa2f.
Report an issue: GitHub.