{"record":{"id":"06cb3aefc828e03b","repo":"ipfs/kubo","slug":"decoding-old-private-key-v","errorCode":null,"errorMessage":"decoding old private key (%v)","messagePattern":"decoding old private key \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/commands/keystore.go","lineNumber":804,"sourceCode":"\tvar identity config.Identity\n\tif nBitsGiven {\n\t\tidentity, err = config.CreateIdentity(out, []options.KeyGenerateOption{\n\t\t\toptions.Key.Size(nBitsForKeypair),\n\t\t\toptions.Key.Type(algorithm),\n\t\t})\n\t} else {\n\t\tidentity, err = config.CreateIdentity(out, []options.KeyGenerateOption{\n\t\t\toptions.Key.Type(algorithm),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"creating identity (%v)\", err)\n\t}\n\n\t// Save old identity to keystore\n\toldPrivKey, err := cfg.Identity.DecodePrivateKey(\"\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"decoding old private key (%v)\", err)\n\t}\n\tkeystore := repo.Keystore()\n\tif err := keystore.Put(oldKey, oldPrivKey); err != nil {\n\t\treturn fmt.Errorf(\"saving old key in keystore (%v)\", err)\n\t}\n\n\t// Update identity\n\tcfg.Identity = identity\n\n\t// Write config file to repo\n\tif err = repo.SetConfig(cfg); err != nil {\n\t\treturn fmt.Errorf(\"saving new key to config (%v)\", err)\n\t}\n\treturn nil\n}\n\nfunc keyOutputListEncoders() cmds.EncoderFunc {\n\treturn cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, list *KeyOutputList) error {","sourceCodeStart":786,"sourceCodeEnd":822,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/keystore.go#L786-L822","documentation":"Before overwriting the identity, doRotate decodes the current node's private key from cfg.Identity.PrivKey using cfg.Identity.DecodePrivateKey(\"\"). Failure to parse the base64-encoded stored key is wrapped as \"decoding old private key (%v)\". This means the repo's existing identity is unusable, and rotation cannot back it up.","triggerScenarios":"Identity.PrivKey in config is corrupted, truncated, hand-edited, or not valid base64/libp2p protobuf key encoding; config from a different format/version.","commonSituations":"Manual config edits that mangled the PrivKey string; copy-paste of config between machines dropping characters; very old repo formats; disk corruption.","solutions":["Verify PrivKey is intact base64 (`base64 -d <<< \"$KEY\" >/dev/null && echo ok`)","Restore Identity.PrivKey from a config backup — do NOT proceed with rotate without the old key, it will be lost","If the old key is unrecoverable and the node is disposable, back up config, replace Identity with a fresh key (`ipfs init` style generation) instead of using key rotate","Never hand-edit the PrivKey field"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"key=$(jq -r .Identity.PrivKey \"$IPFS_PATH/config\")\necho \"$key\" | base64 -d > /dev/null && echo \"PrivKey decodes OK\" || echo \"PrivKey corrupted\"","typeGuard":null,"tryCatchPattern":"if err := doRotate(...); err != nil {\n    if strings.Contains(err.Error(), \"decoding old private key\") {\n        // STOP: do not retry blindly; restore Identity.PrivKey from backup first\n    }\n}","preventionTips":["Never hand-edit Identity.PrivKey","Keep a backup of $IPFS_PATH/config with the working PrivKey","Verify `ipfs id` works before attempting rotate"],"tags":["crypto","identity","config","data-loss"],"backgroundTag":"corrupt-private-key","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}