keys: skip bad keys when listing (#11115)
Change the `ipfs key list` behavior to log an error and continue listing keys when a key cannot be read from the keystore or decoded. Closes: #11102
Andrew Gillis committed
Jan 7, 2026 at 09:56 UTC
566f8ba63f185a64ec676f1b1af5e3a61b6e174c
3 files changed
+17
-9
core/commands/keystore.go
+2
-2
@@ -458,7 +458,7 @@ var keyListCmd = &cmds.Command{
458
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
459
keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.OptionIPNSBase.Name()].(string))
460
if err != nil {
461
- return err
461
+ return fmt.Errorf("cannot get key encoder: %w", err)
462
}
463
464
api, err := cmdenv.GetApi(env, req)
@@ -468,7 +468,7 @@ var keyListCmd = &cmds.Command{
468
469
keys, err := api.Key().List(req.Context)
470
if err != nil {
471
- return err
471
+ return fmt.Errorf("listing keys failed: %w", err)
472
}
473
474
list := make([]KeyOutput, 0, len(keys))
core/coreapi/key.go
+10
-7
@@ -29,7 +29,7 @@ type key struct {
29
func newKey(name string, pid peer.ID) (*key, error) {
30
p, err := path.NewPath("/ipns/" + ipns.NameFromPeer(pid).String())
31
if err != nil {
32
- return nil, err
32
+ return nil, fmt.Errorf("cannot create new key: %w", err)
33
}
34
return &key{
35
name: name,
@@ -121,34 +121,37 @@ func (api *KeyAPI) List(ctx context.Context) ([]coreiface.Key, error) {
121
122
keys, err := api.repo.Keystore().List()
123
if err != nil {
124
- return nil, err
124
+ return nil, fmt.Errorf("cannot list keys in keystore: %w", err)
125
}
126
127
sort.Strings(keys)
128
129
- out := make([]coreiface.Key, len(keys)+1)
129
+ out := make([]coreiface.Key, 1, len(keys)+1)
130
out[0], err = newKey("self", api.identity)
131
if err != nil {
132
return nil, err
133
}
134
135
- for n, k := range keys {
135
+ for _, k := range keys {
136
privKey, err := api.repo.Keystore().Get(k)
137
if err != nil {
138
- return nil, err
138
+ log.Errorf("cannot get key from keystore: %s", err)
139
+ continue
140
}
141
142
pubKey := privKey.GetPublic()
143
144
pid, err := peer.IDFromPublicKey(pubKey)
145
if err != nil {
145
- return nil, err
146
+ log.Errorf("cannot decode public key: %s", err)
147
+ continue
148
}
149
148
- out[n+1], err = newKey(k, pid)
150
+ k, err := newKey(k, pid)
151
if err != nil {
152
return nil, err
153
}
154
+ out = append(out, k)
155
}
156
return out, nil
157
}
docs/changelogs/v0.40.md
+5
@@ -12,6 +12,7 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team.
12
- [🔦 Highlights](#-highlights)
13
- [Routing V1 HTTP API now exposed by default](#routing-v1-http-api-now-exposed-by-default)
14
- [Track total size when adding pins](#track-total-size-when-adding-pins)
15
+ - [Skip bad keys when listing](#skip_bad_keys_when_listing)
16
- [📦️ Dependency updates](#-dependency-updates)
17
- [📝 Changelog](#-changelog)
18
- [👨👩👧👦 Contributors](#-contributors)
@@ -33,6 +34,10 @@ Example output:
34
Fetched/Processed 336 nodes (83 MB)
35
```
36
37
+#### Skip bad keys when listing
38
+
39
+Change the `ipfs key list` behavior to log an error and continue listing keys when a key cannot be read from the keystore or decoded.
40
+
41
#### 📦️ Dependency updates
42
43
- update `go-libp2p` to [v0.46.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.46.0)