{"record":{"id":"e00479ccbd66cbee","repo":"ipfs/kubo","slug":"opening-repo-v","errorCode":null,"errorMessage":"opening repo (%v)","messagePattern":"opening repo \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/keystore.go","lineNumber":775,"sourceCode":"\t\tcctx := env.(*oldcmds.Context)\n\t\tnBitsForKeypair, nBitsGiven := req.Options[keyStoreSizeOptionName].(int)\n\t\talgorithm, _ := req.Options[keyStoreTypeOptionName].(string)\n\t\toldKey, ok := req.Options[oldKeyOptionName].(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"keystore name for backing up old key must be provided\")\n\t\t}\n\t\tif oldKey == \"self\" {\n\t\t\treturn fmt.Errorf(\"keystore name for back up cannot be named 'self'\")\n\t\t}\n\t\treturn doRotate(os.Stdout, cctx.ConfigRoot, oldKey, algorithm, nBitsForKeypair, nBitsGiven)\n\t},\n}\n\nfunc doRotate(out io.Writer, repoRoot string, oldKey string, algorithm string, nBitsForKeypair int, nBitsGiven bool) error {\n\t// Open repo\n\trepo, err := fsrepo.Open(repoRoot)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"opening repo (%v)\", err)\n\t}\n\tdefer repo.Close()\n\n\t// Read config file from repo\n\tcfg, err := repo.Config()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reading config from repo (%v)\", err)\n\t}\n\n\t// Generate new identity\n\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{","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/keystore.go#L757-L793","documentation":"doRotate opens the IPFS repository (fsrepo.Open) to read the config and access the keystore. If the repo cannot be opened — because it is already locked by a running daemon, does not exist, or is on an incompatible version — the error is wrapped as \"opening repo (%v)\". The underlying fsrepo error is preserved in the message.","triggerScenarios":"Running `ipfs key rotate` while the daemon is running (repo lock held); IPFS_PATH points to a directory that was never initialized; repo needs a migration (version downgrade/upgrade); corrupted repo lock file.","commonSituations":"Forgetting to `ipfs daemon stop` before rotating; wrong IPFS_PATH environment variable; rotating after an upgrade that left the repo at a newer version than the binary supports.","solutions":["Stop the daemon first: `ipfs shutdown` or kill the process, then retry rotate","Verify IPFS_PATH points at the initialized repo (`ipfs repo version`, `ls $IPFS_PATH`)","If a migration is required, run `ipfs repo migrate` (or the matching binary version) before rotating","Remove a stale $IPFS_PATH/repo.lock only if no daemon is running"],"exampleFix":"// before\nipfs key rotate --old-key=old  # daemon running -> lock error\n// after\nipfs shutdown\nipfs key rotate --old-key=old","handlingStrategy":"try-catch","validationCode":"// before rotating\ntest -f \"$IPFS_PATH/config\" || { echo \"no repo at $IPFS_PATH\"; exit 1; }\npgrep -f 'ipfs daemon' && { echo 'stop daemon first'; exit 1; }","typeGuard":null,"tryCatchPattern":"if err := doRotate(out, repoRoot, oldKey, alg, bits, given); err != nil {\n    if strings.Contains(err.Error(), \"opening repo\") {\n        // check daemon lock, IPFS_PATH, repo version\n        var inner = errors.Unwrap(err)\n        log.Printf(\"fsrepo open failed: %v\", inner)\n    }\n}","preventionTips":["Always stop the daemon before key rotate","Pin IPFS_PATH explicitly in scripts","Keep repo and binary versions in sync; run migrations promptly"],"tags":["repo","lock","fsrepo","cli"],"backgroundTag":"repo-lock-held","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"}