canopy-network/canopy · error
nickname already used
Error message
nickname already used
What it means
Keystore.Import returns "nickname already used" when importing a key with an ImportOptions.Nickname that is already mapped to a different address in the keystore's NicknameMap. Each nickname must uniquely identify one address to keep lookups unambiguous.
Source
Thrown at lib/crypto/keystore.go:97
func (ks *Keystore) Import(encrypted *EncryptedPrivateKey, opts ImportOpts) error {
// TODO: better naming
encrypted.KeyAddress = hex.EncodeToString(opts.Address)
encrypted.KeyNickname = opts.Nickname
// this is needed to prevent saving various nicknames for the same address
var oldNickname string
oldKey := ks.AddressMap[encrypted.KeyAddress]
if oldKey != nil {
oldNickname = oldKey.KeyNickname
}
if oldNickname != "" {
delete(ks.NicknameMap, oldNickname)
}
if opts.Nickname != "" {
_, ok := ks.NicknameMap[opts.Nickname]
if ok && opts.Nickname != oldNickname {
return errors.New("nickname already used")
}
ks.NicknameMap[opts.Nickname] = encrypted.KeyAddress
}
ks.AddressMap[encrypted.KeyAddress] = encrypted
return nil
}
type ImportRawOpts struct {
Nickname string
}
// ImportRaw() imports a non-encrypted private key to the store, but encrypts it given a password
func (ks *Keystore) ImportRaw(privateKeyBytes []byte, password string, opts ImportRawOpts) (address string, err error) {
if password == "" {
return "", fmt.Errorf("invalid password")
}View on GitHub (pinned to ee8197d91d)
Solutions
- Pick a unique nickname or generate one (suffix/timestamp) before importing
- Omit opts.Nickname to import without a nickname
- If re-importing the same key intentionally, clear/replace the old nickname mapping first
Example fix
// before
_, err := ks.ImportRaw(pk, &keystore.ImportOptions{Nickname: "validator"}) // second import
// after
if _, exists := ks.NicknameMap["validator"]; exists {
opts.Nickname = "validator-2"
}
_, err := ks.ImportRaw(pk, opts) Defensive patterns
Strategy: try-catch
Validate before calling
if opts.Nickname != "" {
if addr, ok := ks.NicknameMap[opts.Nickname]; ok && addr != encrypted.KeyAddress {
opts.Nickname = opts.Nickname + "-" + fmt.Sprintf("%d", time.Now().Unix())
}
} Try / catch
_, err := ks.ImportRaw(pk, opts)
if err != nil && strings.Contains(err.Error(), "nickname already used") {
opts.Nickname = uniquify(opts.Nickname)
_, err = ks.ImportRaw(pk, opts)
} Prevention
- Check NicknameMap before importing with a fixed nickname
- Make import scripts idempotent (reuse the existing entry if the address matches)
- Generate nicknames with unique suffixes in automation
When it happens
Trigger: Import/ImportRaw called twice with the same opts.Nickname for two different keys; renaming a key to a nickname owned by another key.
Common situations: Re-running an import script that reuses a fixed nickname; exporting/importing across keystores where a nickname already exists; automation that doesn't detect existing nicknames.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
AI-assisted analysis of canopy-network/canopy@ee8197d91d (2026-09-06).
Data as JSON: /api/errors/985da1392791de56.
Report an issue: GitHub.