{"record":{"id":"674f30d95f816992","repo":"netbirdio/netbird","slug":"failed-to-parse-private-root-key-w","errorCode":null,"errorMessage":"failed to parse private root key: %w","messagePattern":"failed to parse private root key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/artifactkey.go","lineNumber":107,"sourceCode":"\tif err := bundlePubKeysCmd.MarkFlagRequired(\"artifact-pub-key-file\"); err != nil {\n\t\tpanic(fmt.Errorf(\"mark artifact-pub-key-file as required: %w\", err))\n\t}\n\tif err := bundlePubKeysCmd.MarkFlagRequired(\"bundle-pub-key-file\"); err != nil {\n\t\tpanic(fmt.Errorf(\"mark bundle-pub-key-file as required: %w\", err))\n\t}\n}\n\nfunc handleCreateArtifactKey(cmd *cobra.Command, rootPrivKeyFile, artifactPrivKeyFile, artifactPubKeyFile string, expiration time.Duration) error {\n\tcmd.Println(\"Creating new artifact signing key...\")\n\n\tprivKeyPEM, err := os.ReadFile(rootPrivKeyFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read root private key file: %w\", err)\n\t}\n\n\tprivateRootKey, err := reposign.ParseRootKey(privKeyPEM)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse private root key: %w\", err)\n\t}\n\n\tartifactKey, privPEM, pubPEM, signature, err := reposign.GenerateArtifactKey(privateRootKey, expiration)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"generate artifact key: %w\", err)\n\t}\n\n\tif err := os.WriteFile(artifactPrivKeyFile, privPEM, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write private key file (%s): %w\", artifactPrivKeyFile, err)\n\t}\n\n\tif err := os.WriteFile(artifactPubKeyFile, pubPEM, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write public key file (%s): %w\", artifactPubKeyFile, err)\n\t}\n\n\tsignatureFile := artifactPubKeyFile + \".sig\"\n\tif err := os.WriteFile(signatureFile, signature, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write signature file (%s): %w\", signatureFile, err)","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/artifactkey.go#L89-L125","documentation":"reposign.ParseRootKey rejected the PEM bytes read from --root-private-key-file. ParseRootKey requires a single PEM block of the exact root-private-key type tag with no trailing PEM data and a valid unmarshalled Ed25519 key, so the file is not a root private key in the format this tool produces.","triggerScenarios":"Passing a public key instead of the private key; passing an artifact private key or a generic OpenSSH/openssl ed25519 key whose PEM header does not match the expected root type tag; a file with multiple concatenated PEM blocks; truncated or corrupted PEM.","commonSituations":"Mixing up the outputs of create-root-key (priv vs pub files); exporting a key with openssl and assuming compatibility; hand-editing or concatenating key files.","solutions":["Use the private key file emitted by the create-root-key command, not the .pub companion and not an artifact key","Inspect the PEM header line and confirm it matches the root private key type the tool generates","If the key was produced by another tool, regenerate a root key with create-root-key and re-issue artifact keys"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm the PEM block type before invoking the CLI\nblock, _ := pem.Decode(data)\nif block == nil || block.Type != rootPrivateKeyPEMType {\n    return fmt.Errorf(\"file is not a root private key PEM\")\n}","typeGuard":"func isRootPrivateKeyPEM(data []byte) bool {\n    block, _ := pem.Decode(data)\n    return block != nil && block.Type == rootPrivateKeyPEMType\n}","tryCatchPattern":null,"preventionTips":["Keep a naming convention that separates root vs artifact and priv vs pub files","Never convert keys through external tools; use create-root-key output verbatim","Verify the '-----BEGIN ...-----' header in CI before the signing step"],"tags":["cli","cryptography","pem","parsing","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}