netbirdio/netbird · error
read public key file: %w
Error message
read public key file: %w
What it means
os.ReadFile failed on one of the --artifact-pub-key-file entries while looping over the list in handleBundlePubKeys. Note the message does not include the offending pubFile name, so correlate by position/count when multiple files are passed.
Source
Thrown at client/cmd/signer/artifactkey.go:150
func handleBundlePubKeys(cmd *cobra.Command, rootPrivKeyFile string, artifactPubKeyFiles []string, bundlePubKeysFile string) error {
cmd.Println("📦 Bundling public keys into signed package...")
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)
}
publicKeys := make([]reposign.PublicKey, 0, len(artifactPubKeyFiles))
for _, pubFile := range artifactPubKeyFiles {
pubPem, err := os.ReadFile(pubFile)
if err != nil {
return fmt.Errorf("read public key file: %w", err)
}
pk, err := reposign.ParseArtifactPubKey(pubPem)
if err != nil {
return fmt.Errorf("failed to parse artifact key: %w", err)
}
publicKeys = append(publicKeys, pk)
}
parsedKeys, signature, err := reposign.BundleArtifactKeys(privateRootKey, publicKeys)
if err != nil {
return fmt.Errorf("bundle artifact keys: %w", err)
}
if err := os.WriteFile(bundlePubKeysFile, parsedKeys, 0o600); err != nil {
return fmt.Errorf("write public keys file (%s): %w", bundlePubKeysFile, err)
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Iterate the same file list and stat each path before rerunning to find the missing one
- Quote globs and guard empty variables in the invoking script
- Confirm each entry is a readable regular file
Example fix
// before (script)
for f in $PUB_KEYS; do ... done # empty/typo entries slip through silently
// after
for f in $PUB_KEYS; do [ -r "$f" ] || { echo "missing: $f"; exit 1; }; done Defensive patterns
Strategy: validation
Validate before calling
for _, f := range artifactPubKeyFiles {
info, err := os.Stat(f)
if err != nil || info.IsDir() {
log.Fatalf("artifact public key not readable: %s", f)
}
} Prevention
- Check every path in the repeated flag list before invoking the CLI
- Quote globs in shell; bail out when a glob matches nothing
- Assert the count of inputs matches the expected key count in CI
When it happens
Trigger: Any entry in the repeated --artifact-pub-key-file list that does not exist or is unreadable; a trailing empty string from an unquoted, non-expanded shell variable; a directory passed instead of a file.
Common situations: Glob that matched nothing ('*.pub' unexpanded); typos in one of many paths; CI checkout missing one key artifact.
Related errors
- failed to create artifact key: %w
- read root private key file: %w
- write signature file (%s): %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/93e12a3c5a3e47ab.
Report an issue: GitHub.