netbirdio/netbird · error
read artifact file: %w
Error message
read artifact file: %w
What it means
os.ReadFile on the --artifact-file path failed during sign-artifact. The wrapped *fs.PathError carries the real cause: file does not exist, permission denied, or the path is a directory. Note the message omits the path (unlike the .sig write error), which slows down diagnosis.
Source
Thrown at client/cmd/signer/artifactsign.go:141
privKeyPEM = []byte(envKey)
} else if privKeyFile != "" {
// Fall back to file
privKeyPEM, err = os.ReadFile(privKeyFile)
if err != nil {
return fmt.Errorf("read private key file: %w", err)
}
} else {
return fmt.Errorf("artifact private key must be provided via %s environment variable or --artifact-key-file flag", envArtifactPrivateKey)
}
privateKey, err := reposign.ParseArtifactKey(privKeyPEM)
if err != nil {
return fmt.Errorf("failed to parse artifact private key: %w", err)
}
artifactData, err := os.ReadFile(artifactFile)
if err != nil {
return fmt.Errorf("read artifact file: %w", err)
}
signature, err := reposign.SignData(privateKey, artifactData)
if err != nil {
return fmt.Errorf("sign artifact: %w", err)
}
sigFile := artifactFile + ".sig"
if err := os.WriteFile(artifactFile+".sig", signature, 0o600); err != nil {
return fmt.Errorf("write signature file (%s): %w", sigFile, err)
}
cmd.Printf("✅ Artifact signed successfully.\n")
cmd.Printf("Signature file: %s\n", sigFile)
return nil
}
func handleVerifyArtifact(cmd *cobra.Command, pubKeyFile, artifactFile, signatureFile string) error {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Verify the path exists and is a regular file: ls -l <path>, and use an absolute path
- Fix pipeline ordering so signing runs after the artifact is fully written
- Check read permission on the file and traverse permission on parent directories
- If diagnosing in scripts, reproduce with cat <path>
Example fix
// before
artifactData, err := os.ReadFile(artifactFile)
if err != nil {
return fmt.Errorf("read artifact file: %w", err)
}
// after
artifactData, err := os.ReadFile(artifactFile)
if err != nil {
return fmt.Errorf("read artifact file %s: %w", artifactFile, err)
} Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(artifactFile); err != nil || info.IsDir() || info.Size() == 0 {
log.Fatalf("artifact %s missing, empty, or not a file: %v", artifactFile, err)
} Prevention
- Make the signing step depend on the build artifact being produced and non-empty
- Use absolute paths in release scripts
- Fail the pipeline on empty build outputs before signing
When it happens
Trigger: Running the signer from a different working directory with a relative path; signing a file the build step has not produced yet; passing a directory as --artifact-file; no read permission on the file.
Common situations: CI step ordering: sign-artifact runs before goreleaser/build finishes; path typo or wrong release directory; artifact owned by another user.
Related errors
- write signature file (%s): %w
- read public key file: %w
- read signature file: %w
- read artifact key file: %w
- read root key file: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/caf9c59d95397f8c.
Report an issue: GitHub.