{"record":{"id":"972bd821ea87cc9f","repo":"ipfs/kubo","slug":"saving-new-key-to-config-v","errorCode":null,"errorMessage":"saving new key to config (%v)","messagePattern":"saving new key to config \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/keystore.go","lineNumber":816,"sourceCode":"\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 {\n\t\twithID, _ := req.Options[\"l\"].(bool)\n\n\t\ttw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)\n\t\tfor _, s := range list.Keys {\n\t\t\tif withID {\n\t\t\t\tfmt.Fprintf(tw, \"%s\\t%s\\t\\n\", s.Id, cmdenv.EscNonPrint(s.Name))\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(tw, \"%s\\n\", cmdenv.EscNonPrint(s.Name))\n\t\t\t}\n\t\t}\n\t\ttw.Flush()\n\t\treturn nil","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/keystore.go#L798-L834","documentation":"The final step of doRotate writes the config containing the NEW identity back to the repo via repo.SetConfig. Failure is wrapped as \"saving new key to config (%v)\". By this point the old key has already been saved to the keystore, so nothing is lost, but the node still runs the old identity until a successful write.","triggerScenarios":"Read-only filesystem or permissions error writing $IPFS_PATH/config; disk full during write; config changed concurrently and rejected; serialization failure (rare).","commonSituations":"Running as wrong user after a sudo invocation changed file ownership; full disk mid-rotation; another process holding/rewriting the config.","solutions":["Fix filesystem permissions/ownership of $IPFS_PATH/config and retry rotate","Free disk space (`df -h`) and retry","Re-run the whole `ipfs key rotate --old-key=<name>` command — old key backup already exists, use a new backup name or check `ipfs key list`","Verify config validity afterwards with `ipfs config show`"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"[ -w \"$IPFS_PATH/config\" ] && echo \"config writable\" || echo \"fix permissions\"\ndf -h \"$IPFS_PATH\" | awk 'NR==2 {exit ($5+0 >= 95) ? 1 : 0}'","typeGuard":null,"tryCatchPattern":"if err := doRotate(...); err != nil {\n    if strings.Contains(err.Error(), \"saving new key to config\") {\n        // old key already backed up; fix filesystem and re-run rotate\n    }\n}","preventionTips":["Verify write access to $IPFS_PATH/config before rotating","Monitor disk space in automation","Re-run rotate after a failed SetConfig; backup naming should account for retries"],"tags":["config","filesystem","cli"],"backgroundTag":"config-write-failed","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"}