netbirdio/netbird · error

failed to sign artifact: %w

Error message

failed to sign artifact: %w

What it means

Generic wrapper from the sign-artifact RunE around handleSignArtifact. It wraps one of: reading the artifact private key (env or file), ParseArtifactKey PEM failures, reading --artifact-file, or reposign.SignData errors such as 'artifact length must be positive, got 0' (empty artifact) and 'artifact key expired at ...'.

Source

Thrown at client/cmd/signer/artifactsign.go:38

	verifyArtifactPubKeyFile    string
	verifyArtifactFile          string
	verifyArtifactSignatureFile string

	verifyArtifactKeyPubKeyFile     string
	verifyArtifactKeyRootPubKeyFile string
	verifyArtifactKeySignatureFile  string
	verifyArtifactKeyRevocationFile string
)

var signArtifactCmd = &cobra.Command{
	Use:   "sign-artifact",
	Short: "Sign an artifact using an artifact private key",
	Long: `Sign a software artifact (e.g., update bundle or binary) using the artifact's private key.
This command produces a detached signature that can be verified using the corresponding artifact public key.`,
	SilenceUsage: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		if err := handleSignArtifact(cmd, signArtifactPrivKeyFile, signArtifactArtifactFile); err != nil {
			return fmt.Errorf("failed to sign artifact: %w", err)
		}
		return nil
	},
}

var verifyArtifactCmd = &cobra.Command{
	Use:          "verify-artifact",
	Short:        "Verify an artifact signature using an artifact public key",
	Long:         `Verify a software artifact signature using the artifact's public key.`,
	SilenceUsage: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		if err := handleVerifyArtifact(cmd, verifyArtifactPubKeyFile, verifyArtifactFile, verifyArtifactSignatureFile); err != nil {
			return fmt.Errorf("failed to verify artifact: %w", err)
		}
		return nil
	},
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Read the chained cause after 'failed to sign artifact:' and address that specific failure
  2. If 'artifact key expired', mint a fresh key with create-artifact-key and re-sign
  3. If 'artifact length must be positive', fix the build so the artifact file is non-empty before signing
  4. Provide the key via NB_ARTIFACT_PRIV_KEY or a valid --artifact-key-file
Defensive patterns

Strategy: try-catch

Validate before calling

// In release scripts: refuse to sign empty artifacts and expired keys first
[ -s "$ARTIFACT" ] || { echo "artifact is empty"; exit 1; }
[ -n "${NB_ARTIFACT_PRIV_KEY:-}" ] || [ -r "$KEY_FILE" ] || { echo "no signing key"; exit 1; }

Try / catch

err := signArtifactCmd.Execute()
if err != nil {
    msg := err.Error()
    switch {
    case strings.Contains(msg, "expired"):
        // rotate artifact key, then re-sign
    case strings.Contains(msg, "length must be positive"):
        // fix the build producing an empty artifact
    default:
        log.Fatalf("sign-artifact failed: %v", err)
    }
}

Prevention

When it happens

Trigger: Signing with an expired artifact key; signing a zero-byte artifact file; missing key file without NB_ARTIFACT_PRIV_KEY set; malformed key PEM; unreadable artifact path.

Common situations: Release pipelines that sign after the artifact key's planned lifetime; an empty build output passed to --artifact-file; key sourced from a secret env var that was not injected into the job.

Related errors


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