netbirdio/netbird · error
failed to parse signature: %w
Error message
failed to parse signature: %w
What it means
reposign.ParseSignature failed: it json.Unmarshals the .sig file into {signature, timestamp, key_id, algorithm, hash_algo} (reposign/signature.go:17-24). It fails when the file is not this JSON bundle — e.g. a raw Ed25519 signature from openssl, an HTML error page saved as .sig, or a truncated download. Field-level failures include a key_id that is not exactly 16 hex chars and a timestamp that is not valid RFC3339 (KeyID.UnmarshalJSON and time parsing).
Source
Thrown at client/cmd/signer/artifactsign.go:187
if err != nil {
return fmt.Errorf("failed to parse artifact public key: %w", err)
}
// Read artifact data
artifactData, err := os.ReadFile(artifactFile)
if err != nil {
return fmt.Errorf("read artifact file: %w", err)
}
// Read signature
sigBytes, err := os.ReadFile(signatureFile)
if err != nil {
return fmt.Errorf("read signature file: %w", err)
}
signature, err := reposign.ParseSignature(sigBytes)
if err != nil {
return fmt.Errorf("failed to parse signature: %w", err)
}
// Validate artifact
if err := reposign.ValidateArtifact([]reposign.PublicKey{publicKey}, artifactData, *signature); err != nil {
return fmt.Errorf("artifact verification failed: %w", err)
}
cmd.Println("✅ Artifact signature is valid")
cmd.Printf("Artifact: %s\n", artifactFile)
cmd.Printf("Signed by key: %s\n", signature.KeyID)
cmd.Printf("Signature timestamp: %s\n", signature.Timestamp.Format("2006-01-02 15:04:05 MST"))
return nil
}
func handleVerifyArtifactKey(cmd *cobra.Command, artifactKeyFile, rootKeyFile, signatureFile, revocationFile string) error {
cmd.Println("🔍 Verifying artifact key...")
// Read artifact key dataView on GitHub (pinned to 93e97f4bf1)
Solutions
- Confirm the .sig is the signer's JSON bundle: cat <file>.sig | jq . should show signature, timestamp, key_id, algorithm=ed25519, hash_algo=blake2s
- If the signature came from another tool, re-sign with `signer sign-artifact` instead
- Re-download the .sig and check it is not an error page or truncated (size sanity check)
- Verify key_id is a 16-character hex string and timestamp parses as RFC3339
Example fix
// before (raw openssl signature passed as .sig) openssl pkeyutl -sign -inkey artifact-key.pem -rawin -in netbird > netbird.sig // after (signer produces the JSON bundle the verifier parses) ./signer sign-artifact --artifact-key-file artifact-key.pem --artifact-file netbird
Defensive patterns
Strategy: validation
Validate before calling
if !json.Valid(sigBytes) {
log.Fatal("signature file is not the signer's JSON bundle")
} Type guard
func looksLikeSignatureBundle(data []byte) bool {
var s struct {
Signature []byte `json:"signature"`
Timestamp string `json:"timestamp"`
KeyID string `json:"key_id"`
}
return json.Unmarshal(data, &s) == nil && len(s.Signature) > 0 && len(s.KeyID) == 16
} Prevention
- Never substitute external signing tools for sign-artifact; the .sig format is a JSON bundle, not a raw signature
- Sanity-check downloaded .sig files with jq before verifying
When it happens
Trigger: Using `openssl dgst -sign` output as the .sig; .sig downloaded from a URL that returned a 404 page; hand-edited JSON with a shortened key_id; base64 signature containing invalid characters.
Common situations: Mixing external signing tooling with the NetBird signer format; partial download in CI; someone pretty-printed or re-serialized the JSON and broke a field.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse artifact private key: %w
- sign artifact: %w
- failed to parse artifact public key: %w
- artifact verification failed: %w
- failed to parse root public key(s): %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/69413e8f1abda729.
Report an issue: GitHub.