netbirdio/netbird · error
write signature file (%s): %w
Error message
write signature file (%s): %w
What it means
os.WriteFile failed for the detached root-key signature written next to the public key at the path '<--artifact-pub-key-file>.sig' with mode 0600. This is the last of three writes in handleCreateArtifactKey, so a failure here leaves the priv and pub key files on disk without their signature.
Source
Thrown at client/cmd/signer/artifactkey.go:125
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)
}
signatureFile := artifactPubKeyFile + ".sig"
if err := os.WriteFile(signatureFile, signature, 0o600); err != nil {
return fmt.Errorf("write signature file (%s): %w", signatureFile, err)
}
cmd.Printf("✅ Artifact key created successfully.\n")
cmd.Printf("%s\n", artifactKey.String())
return nil
}
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)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Remove or fix ownership of a stale '<pub>.sig' file (rm/chown) and rerun
- Confirm write permission on the whole output directory, since priv, pub, and .sig land side by side
- Free disk space if the error reports ENOSPC
Defensive patterns
Strategy: validation
Validate before calling
sigFile := artifactPubKeyFile + ".sig"
if err := os.Remove(sigFile); err != nil && !os.IsNotExist(err) { ... } // clear stale ownership conflicts
os.MkdirAll(filepath.Dir(sigFile), 0o700) Prevention
- Rerun signing steps under a single consistent uid to avoid mixed-ownership files
- Treat key directories as disposable: recreate them each pipeline run
- Check disk space before long signing jobs
When it happens
Trigger: The .sig path being un-writable specifically, e.g. an existing .sig owned by another user or a read-only file at that exact name; disk full after the two key writes; directory made read-only between runs.
Common situations: Rerunning create-artifact-key into a directory where a previous run (possibly as root) left a .sig with different ownership; full disks after large artifacts; immutable/RO mount for secrets.
Related errors
- failed to create artifact key: %w
- read root private key file: %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/e0c2eb2b6b4e3d19.
Report an issue: GitHub.