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

  1. Verify the path exists and is a regular file: ls -l <path>, and use an absolute path
  2. Fix pipeline ordering so signing runs after the artifact is fully written
  3. Check read permission on the file and traverse permission on parent directories
  4. 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

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


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/caf9c59d95397f8c. Report an issue: GitHub.