/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/libkb/errors.go
2 976 строк
71 KB
zoom-ua
modernize error handling with errors.As/Is (#29350)
25 июн 2026, 17:41
Не верифицирован
25 июн 2026, 17:41
e09e254
Код
Авторство
О чём код?
// Copyright 2015 Keybase, Inc. All rights reserved. Use of // this source code is governed by the included BSD license. package libkb import ( "encoding/hex" "errors" "fmt" "os" "os/exec" "runtime" "strings" "time" "github.com/keybase/client/go/gregor" "github.com/keybase/client/go/kbcrypto" "github.com/keybase/client/go/protocol/chat1" "github.com/keybase/client/go/protocol/gregor1" keybase1 "github.com/keybase/client/go/protocol/keybase1" ) // ============================================================================= // type ProofError interface { error GetProofStatus() keybase1.ProofStatus GetDesc() string } func ProofErrorIsSoft(pe ProofError) bool { s := pe.GetProofStatus() return (s >= keybase1.ProofStatus_BASE_ERROR && s < keybase1.ProofStatus_BASE_HARD_ERROR) } func ProofErrorIsPvlBad(pe ProofError) bool { s := pe.GetProofStatus() switch s { case keybase1.ProofStatus_INVALID_PVL: return true case keybase1.ProofStatus_MISSING_PVL: return true default: return false } } func ProofErrorToState(pe ProofError) keybase1.ProofState { if pe == nil { return keybase1.ProofState_OK } switch pe.GetProofStatus() { case keybase1.ProofStatus_NO_HINT: return keybase1.ProofState_SIG_HINT_MISSING case keybase1.ProofStatus_UNKNOWN_TYPE: return keybase1.ProofState_UNKNOWN_TYPE case keybase1.ProofStatus_UNCHECKED: return keybase1.ProofState_UNCHECKED default: return keybase1.ProofState_TEMP_FAILURE } } type ProofErrorImpl struct { Status keybase1.ProofStatus Desc string } func NewProofError(s keybase1.ProofStatus, d string, a ...any) *ProofErrorImpl { // Don't do string interpolation if there are no substitution arguments. // Fixes double-interpolation when deserializing an object. if len(a) == 0 { return &ProofErrorImpl{s, d} } return &ProofErrorImpl{s, fmt.Sprintf(d, a...)} } func NewInvalidPVLSelectorError(selector keybase1.SelectorEntry) error { return NewProofError( keybase1.ProofStatus_INVALID_PVL, "JSON selector entry must be a string, int, or 'all' %v", selector, ) } func (e *ProofErrorImpl) Error() string { return fmt.Sprintf("%s (code=%d)", e.Desc, int(e.Status)) } func (e *ProofErrorImpl) GetProofStatus() keybase1.ProofStatus { return e.Status } func (e *ProofErrorImpl) GetDesc() string { return e.Desc } type ProofAPIError struct { ProofErrorImpl url string } var ProofErrorDNSOverTor = &ProofErrorImpl{ Status: keybase1.ProofStatus_TOR_SKIPPED, Desc: "DNS proofs aren't reliable over Tor", } var ProofErrorHTTPOverTor = &ProofErrorImpl{ Status: keybase1.ProofStatus_TOR_SKIPPED, Desc: "HTTP proofs aren't reliable over Tor", } var ProofErrorUnchecked = &ProofErrorImpl{ Status: keybase1.ProofStatus_UNCHECKED, Desc: "Proof unchecked due to privacy concerns", } type TorSessionRequiredError struct{} func (t TorSessionRequiredError) Error() string { return "We can't send out PII in Tor-Strict mode; but it's needed for this operation" } func NewProofAPIError(s keybase1.ProofStatus, u string, d string, a ...any) *ProofAPIError { base := NewProofError(s, d, a...) return &ProofAPIError{*base, u} } // ============================================================================= func XapiError(err error, u string) *ProofAPIError { var ae *APIError if errors.As(err, &ae) { var code keybase1.ProofStatus switch ae.Code / 100 { case 3: code = keybase1.ProofStatus_HTTP_300 case 4: if ae.Code == 429 { code = keybase1.ProofStatus_HTTP_429 } else { code = keybase1.ProofStatus_HTTP_400 } case 5: code = keybase1.ProofStatus_HTTP_500 default: code = keybase1.ProofStatus_HTTP_OTHER } return NewProofAPIError(code, u, "%s", ae.Msg) } return NewProofAPIError(keybase1.ProofStatus_INTERNAL_ERROR, u, "%s", err.Error()) } // ============================================================================= type FailedAssertionError struct { user string bad []AssertionURL } func (u FailedAssertionError) Error() string { v := make([]string, len(u.bad)) for i, u := range u.bad { v[i] = u.String() } return ("for " + u.user + ", the follow assertions failed: " + strings.Join(v, ", ")) } // ============================================================================= type AssertionParseErrorReason int const ( AssertionParseErrorReasonGeneric AssertionParseErrorReason = 0 AssertionParseErrorReasonUnexpectedOR AssertionParseErrorReason = 1 ) type AssertionParseError struct { err string reason AssertionParseErrorReason } func (e AssertionParseError) Reason() AssertionParseErrorReason { return e.reason } func (e AssertionParseError) Error() string { return e.err } func NewAssertionParseError(s string, a ...any) AssertionParseError { return AssertionParseError{ reason: AssertionParseErrorReasonGeneric, err: fmt.Sprintf(s, a...), } } func NewAssertionParseErrorWithReason(reason AssertionParseErrorReason, s string, a ...any) AssertionParseError { return AssertionParseError{ reason: reason, err: fmt.Sprintf(s, a...), } } func IsAssertionParseErrorWithReason(err error, reason AssertionParseErrorReason) bool { var aerr AssertionParseError return errors.As(err, &aerr) && aerr.reason == reason } // ============================================================================= type AssertionCheckError struct { err string } func (e AssertionCheckError) Error() string { return e.err } func NewAssertionCheckError(s string, a ...any) AssertionCheckError { return AssertionCheckError{ err: fmt.Sprintf(s, a...), } } // ============================================================================= type NeedInputError struct { err string } func (e NeedInputError) Error() string { return e.err } func NewNeedInputError(s string, a ...any) AssertionParseError { return AssertionParseError{ err: fmt.Sprintf(s, a...), } } // ============================================================================= type WrongKidError struct { wanted, got keybase1.KID } func (w WrongKidError) Error() string { return fmt.Sprintf("Wanted KID=%s; but got KID=%s", w.wanted, w.got) } func NewWrongKidError(w keybase1.KID, g keybase1.KID) WrongKidError { return WrongKidError{w, g} } // ============================================================================= type WrongKeyError struct { wanted, got *PGPFingerprint } func (e WrongKeyError) Error() string { return fmt.Sprintf("Server gave wrong key; wanted %s; got %s", e.wanted, e.got) } // ============================================================================= type UnexpectedKeyError struct{} func (e UnexpectedKeyError) Error() string { return "Found a key or fingerprint when one wasn't expected" } // ============================================================================= type UserNotFoundError struct { UID keybase1.UID Msg string } func (u UserNotFoundError) Error() string { uid := "" if !u.UID.IsNil() { uid = " " + string(u.UID) } msg := "" if u.Msg != "" { msg = " (" + u.Msg + ")" } return fmt.Sprintf("User%s wasn't found%s", uid, msg) } // ============================================================================= type AlreadyRegisteredError struct { UID keybase1.UID } func (u AlreadyRegisteredError) Error() string { return fmt.Sprintf("Already registered (with uid=%s)", u.UID) } // ============================================================================= type WrongSigError struct { b string } func (e WrongSigError) Error() string { return "Found wrong signature: " + e.b } type BadSigError struct { E string } func (e BadSigError) Error() string { return e.E } // ============================================================================= type NotFoundError struct { Msg string } func (e NotFoundError) Error() string { if len(e.Msg) == 0 { return "Not found" } return e.Msg } func IsNotFoundError(err error) bool { var nfe NotFoundError return errors.As(err, &nfe) } func NewNotFoundError(s string) error { return NotFoundError{s} } // ============================================================================= type MissingDelegationTypeError struct{} func (e MissingDelegationTypeError) Error() string { return "DelegationType wasn't set" } // ============================================================================= type NoKeyError struct { Msg string } func (u NoKeyError) Error() string { if len(u.Msg) > 0 { return u.Msg } return "No public key found" } func IsNoKeyError(err error) bool { var nke NoKeyError return errors.As(err, &nke) } type NoSyncedPGPKeyError struct{} func (e NoSyncedPGPKeyError) Error() string { return "No synced secret PGP key found on keybase.io" } // ============================================================================= type NoSecretKeyError struct{} func (u NoSecretKeyError) Error() string { return "No secret key available" } // ============================================================================= type NoPaperKeysError struct{} func (u NoPaperKeysError) Error() string { return "No paper keys available" } // ============================================================================= type TooManyKeysError struct { n int } func (e TooManyKeysError) Error() string { return fmt.Sprintf("Too many keys (%d) found", e.n) } // ============================================================================= type NoSelectedKeyError struct{} func (n NoSelectedKeyError) Error() string { return "Please login again to verify your public key" } // ============================================================================= type KeyCorruptedError struct { Msg string } func (e KeyCorruptedError) Error() string { msg := "Key corrupted" if len(e.Msg) != 0 { msg = msg + ": " + e.Msg } return msg } // ============================================================================= type KeyExistsError struct { Key *PGPFingerprint } func (k KeyExistsError) Error() string { ret := "Key already exists for user" if k.Key != nil { ret = fmt.Sprintf("%s (%s)", ret, k.Key) } return ret } // ============================================================================= type PassphraseError struct { Msg string } func (p PassphraseError) Error() string { msg := "Bad password" if len(p.Msg) != 0 { msg = msg + ": " + p.Msg + "." } return msg } // ============================================================================= type PaperKeyError struct { msg string tryAgain bool } func (p PaperKeyError) Error() string { msg := "Bad paper key: " + p.msg if p.tryAgain { msg += ". Please try again." } return msg } func NewPaperKeyError(s string, t bool) error { return PaperKeyError{msg: s, tryAgain: t} } // ============================================================================= type BadEmailError struct { Msg string } func (e BadEmailError) Error() string { msg := "Bad email" if len(e.Msg) != 0 { msg = msg + ": " + e.Msg } return msg } // ============================================================================= type BadFingerprintError struct { fp1, fp2 PGPFingerprint } func (b BadFingerprintError) Error() string { return fmt.Sprintf("Got bad PGP key; fingerprint %s != %s", b.fp1, b.fp2) } // ============================================================================= type AppStatusError struct { Code int Name string Desc string Fields map[string]string } // If the error is an AppStatusError, returns its code. // Otherwise returns (SCGeneric, false). func GetAppStatusCode(err error) (code keybase1.StatusCode, ok bool) { var ase AppStatusError if errors.As(err, &ase) { return keybase1.StatusCode(ase.Code), true } return keybase1.StatusCode_SCGeneric, false } func (a AppStatusError) IsBadField(s string) bool { _, found := a.Fields[s] return found } func NewAppStatusError(ast *AppStatus) AppStatusError { return AppStatusError{ Code: ast.Code, Name: ast.Name, Desc: ast.Desc, Fields: ast.Fields, } } func (a AppStatusError) Error() string { v := make([]string, len(a.Fields)) i := 0 for k := range a.Fields { v[i] = k i++ } fields := "" if i > 0 { fields = fmt.Sprintf(" (bad fields: %s)", strings.Join(v, ",")) } return fmt.Sprintf("%s%s (error %d)", a.Desc, fields, a.Code) } func (a AppStatusError) WithDesc(desc string) AppStatusError { a.Desc = desc return a } func IsAppStatusCode(err error, code keybase1.StatusCode) bool { var ase AppStatusError return errors.As(err, &ase) && ase.Code == int(code) } func IsEphemeralRetryableError(err error) bool { var ase AppStatusError if !errors.As(err, &ase) { return false } switch keybase1.StatusCode(ase.Code) { case keybase1.StatusCode_SCSigWrongKey, keybase1.StatusCode_SCSigOldSeqno, keybase1.StatusCode_SCEphemeralKeyBadGeneration, keybase1.StatusCode_SCEphemeralKeyUnexpectedBox, keybase1.StatusCode_SCEphemeralKeyMissingBox, keybase1.StatusCode_SCEphemeralKeyWrongNumberOfKeys, keybase1.StatusCode_SCTeambotKeyBadGeneration, keybase1.StatusCode_SCTeambotKeyOldBoxedGeneration: return true default: return false } } // ============================================================================= type GpgError struct { M string } func (e GpgError) Error() string { return fmt.Sprintf("GPG error: %s", e.M) } func ErrorToGpgError(e error) GpgError { return GpgError{e.Error()} } type GpgIndexError struct { lineno int m string } func (e GpgIndexError) Error() string { return fmt.Sprintf("GPG index error at line %d: %s", e.lineno, e.m) } func ErrorToGpgIndexError(l int, e error) GpgIndexError { return GpgIndexError{l, e.Error()} } type GPGUnavailableError struct{} func (g GPGUnavailableError) Error() string { return "GPG is unavailable on this device" } // ============================================================================= type LoginRequiredError struct { Context string } func (e LoginRequiredError) Error() string { msg := "Login required" if len(e.Context) > 0 { msg = fmt.Sprintf("%s: %s", msg, e.Context) } return msg } func NewLoginRequiredError(s string) error { return LoginRequiredError{s} } type ReloginRequiredError struct{} func (e ReloginRequiredError) Error() string { return "Login required due to an unexpected error since your previous login" } type DeviceRequiredError struct{} func (e DeviceRequiredError) Error() string { return "Login required" } type NoSessionError struct{} // KBFS currently matching on this string, so be careful changing this: func (e NoSessionError) Error() string { return "no current session" } // ============================================================================= type LogoutError struct{} func (e LogoutError) Error() string { return "Failed to logout" } // ============================================================================= type LoggedInError struct{} func (e LoggedInError) Error() string { return "You are already logged in as a different user; try logout first" } // ============================================================================= type LoggedInWrongUserError struct { ExistingName NormalizedUsername AttemptedName NormalizedUsername } func (e LoggedInWrongUserError) Error() string { return fmt.Sprintf("Logged in as %q, attempting to log in as %q: try logout first", e.ExistingName, e.AttemptedName) } // ============================================================================= type InternalError struct { Msg string } func (e InternalError) Error() string { return fmt.Sprintf("Internal error: %s", e.Msg) } // ============================================================================= type ServerChainError struct { msg string } func (e ServerChainError) Error() string { return e.msg } func NewServerChainError(d string, a ...any) ServerChainError { return ServerChainError{fmt.Sprintf(d, a...)} } // ============================================================================= type WaitForItError struct{} func (e WaitForItError) Error() string { return "It is advised you 'wait for it'" } // ============================================================================= type InsufficientKarmaError struct { un string } func (e InsufficientKarmaError) Error() string { return "Bad karma" } func NewInsufficientKarmaError(un string) InsufficientKarmaError { return InsufficientKarmaError{un: un} } // ============================================================================= type InvalidHostnameError struct { h string } func (e InvalidHostnameError) Error() string { return "Invalid hostname: " + e.h } func NewInvalidHostnameError(h string) InvalidHostnameError { return InvalidHostnameError{h: h} } // ============================================================================= type WebUnreachableError struct { h string } func (h WebUnreachableError) Error() string { return "Host " + h.h + " is down; tried both HTTPS and HTTP protocols" } func NewWebUnreachableError(h string) WebUnreachableError { return WebUnreachableError{h: h} } // ============================================================================= type ProtocolSchemeMismatch struct { msg string } func (h ProtocolSchemeMismatch) Error() string { return h.msg } func NewProtocolSchemeMismatch(msg string) ProtocolSchemeMismatch { return ProtocolSchemeMismatch{msg: msg} } // ============================================================================= type ProtocolDowngradeError struct { msg string } func (h ProtocolDowngradeError) Error() string { return h.msg } func NewProtocolDowngradeError(msg string) ProtocolDowngradeError { return ProtocolDowngradeError{msg: msg} } // ============================================================================= type ProfileNotPublicError struct { msg string } func (p ProfileNotPublicError) Error() string { return p.msg } func NewProfileNotPublicError(s string) ProfileNotPublicError { return ProfileNotPublicError{msg: s} } // ============================================================================= type BadUsernameError struct { N string msg string } func (e BadUsernameError) Error() string { if len(e.msg) == 0 { return "Bad username: '" + e.N + "'" } return e.msg } func NewBadUsernameError(n string) BadUsernameError { return BadUsernameError{N: n} } func NewBadUsernameErrorWithFullMessage(msg string) BadUsernameError { return BadUsernameError{msg: msg} } // ============================================================================= type NoUsernameError struct{} func (e NoUsernameError) Error() string { return "No username known" } func NewNoUsernameError() NoUsernameError { return NoUsernameError{} } // ============================================================================= type NoKeyringsError struct{} func (k NoKeyringsError) Error() string { return "No keyrings available" } // ============================================================================= type KeyCannotSignError struct{} func (s KeyCannotSignError) Error() string { return "Key cannot create signatures" } type KeyCannotVerifyError struct{} func (k KeyCannotVerifyError) Error() string { return "Key cannot verify signatures" } type KeyCannotEncryptError struct{} func (k KeyCannotEncryptError) Error() string { return "Key cannot encrypt data" } type KeyCannotDecryptError struct{} func (k KeyCannotDecryptError) Error() string { return "Key cannot decrypt data" } type KeyUnimplementedError struct{} func (k KeyUnimplementedError) Error() string { return "Key function isn't implemented yet" } type NoPGPEncryptionKeyError struct { User string HasKeybaseEncryptionKey bool } func (e NoPGPEncryptionKeyError) Error() string { var other string if e.HasKeybaseEncryptionKey { other = "; they do have a keybase key, so you can `keybase encrypt` to them instead" } return fmt.Sprintf("User %s doesn't have a PGP key%s", e.User, other) } type NoNaClEncryptionKeyError struct { Username string HasPGPKey bool HasPUK bool HasDeviceKey bool HasPaperKey bool } func (e NoNaClEncryptionKeyError) Error() string { var other string switch { case e.HasPUK: other = "; they have a per user key, so you can encrypt without the `--no-entity-keys` flag to them instead" case e.HasDeviceKey: other = "; they do have a device key, so you can encrypt without the `--no-device-keys` flag to them instead" case e.HasPaperKey: other = "; they do have a paper key, so you can encrypt without the `--no-paper-keys` flag to them instead" case e.HasPGPKey: other = "; they do have a PGP key, so you can `keybase pgp encrypt` to encrypt for them instead" } return fmt.Sprintf("User %s doesn't have the necessary key type(s)%s", e.Username, other) } type KeyPseudonymError struct { message string } func (e KeyPseudonymError) Error() string { if e.message != "" { return e.message } return "Bad Key Pseydonym or Nonce" } func NewKeyPseudonymError(message string) KeyPseudonymError { return KeyPseudonymError{message: message} } // ============================================================================= type DecryptBadPacketTypeError struct{} func (d DecryptBadPacketTypeError) Error() string { return "Bad packet type; can't decrypt" } type DecryptBadNonceError struct{} func (d DecryptBadNonceError) Error() string { return "Bad packet nonce; can't decrypt" } type DecryptBadSenderError struct{} func (d DecryptBadSenderError) Error() string { return "Bad sender key" } type DecryptWrongReceiverError struct{} func (d DecryptWrongReceiverError) Error() string { return "Bad receiver key" } type DecryptOpenError struct { What string } func NewDecryptOpenError(what string) DecryptOpenError { return DecryptOpenError{What: what} } func (d DecryptOpenError) Error() string { if len(d.What) == 0 { return "box.Open failure; ciphertext was corrupted or wrong key" } return fmt.Sprintf("failed to decrypt '%s'; ciphertext was corrupted or wrong key", d.What) } // ============================================================================= type NoConfigFileError struct{} func (n NoConfigFileError) Error() string { return "No configuration file available" } // ============================================================================= type SelfTrackError struct{} func (e SelfTrackError) Error() string { return "Cannot follow yourself" } // ============================================================================= type NoUIError struct { Which string } func (e NoUIError) Error() string { return fmt.Sprintf("no %s-UI was available", e.Which) } // ============================================================================= type NoConfigWriterError struct{} func (e NoConfigWriterError) Error() string { return "Can't write; no ConfigWriter available" } // ============================================================================= type NoSessionWriterError struct{} func (e NoSessionWriterError) Error() string { return "Can't write; no SessionWriter available" } // ============================================================================= type BadServiceError struct { Service string } func (e BadServiceError) Error() string { return e.Service + ": unsupported service" } type ServiceDoesNotSupportNewProofsError struct { Service string } func (e ServiceDoesNotSupportNewProofsError) Error() string { if len(e.Service) == 0 { return "New proofs of that type are not supported" } return fmt.Sprintf("New %s proofs are not supported", e.Service) } // ============================================================================= type NotConfirmedError struct{} func (e NotConfirmedError) Error() string { return "Not confirmed" } // ============================================================================= type SibkeyAlreadyExistsError struct{} func (e SibkeyAlreadyExistsError) Error() string { return "Key is already selected for use on Keybase" } // ============================================================================= type ProofNotYetAvailableError struct{} func (e ProofNotYetAvailableError) Error() string { return "Proof wasn't available; we'll keep trying" } type ProofNotFoundForServiceError struct { Service string } func (e ProofNotFoundForServiceError) Error() string { return fmt.Sprintf("proof not found for service %q", e.Service) } type ProofNotFoundForUsernameError struct { Service string Username string } func (e ProofNotFoundForUsernameError) Error() string { return fmt.Sprintf("proof not found for %q on %q", e.Username, e.Service) } // ============================================================================= // ============================================================================= type KeyGenError struct { Msg string } func (e KeyGenError) Error() string { return fmt.Sprintf("key generation error: %s", e.Msg) } // ============================================================================= type KeyFamilyError struct { Msg string } func (e KeyFamilyError) Error() string { return fmt.Sprintf("Bad key family: %s", e.Msg) } // ============================================================================= type BadRevocationError struct { msg string } func (e BadRevocationError) Error() string { return fmt.Sprintf("Bad revocation: %s", e.msg) } // ============================================================================= type NoSigChainError struct{} func (e NoSigChainError) Error() string { return "No sigchain was available" } // ============================================================================= type NotProvisionedError struct{} func (e NotProvisionedError) Error() string { return "This device isn't provisioned (no 'device_kid' entry in config.json)" } // ============================================================================= type UIDMismatchError struct { Msg string } func (u UIDMismatchError) Error() string { return fmt.Sprintf("UID mismatch error: %s", u.Msg) } func NewUIDMismatchError(m string) UIDMismatchError { return UIDMismatchError{Msg: m} } // ============================================================================= type KeyRevokedError struct { msg string } func NewKeyRevokedError(m string) KeyRevokedError { return KeyRevokedError{m} } func (r KeyRevokedError) Error() string { return fmt.Sprintf("Key revoked: %s", r.msg) } // ============================================================================= type KeyExpiredError struct { msg string } func (r KeyExpiredError) Error() string { return fmt.Sprintf("Key expired: %s", r.msg) } // ============================================================================= type UnknownKeyTypeError struct { typ kbcrypto.AlgoType } func (e UnknownKeyTypeError) Error() string { return fmt.Sprintf("Unknown key type: %d", e.typ) } // ============================================================================= type SelfNotFoundError struct { msg string } func (e SelfNotFoundError) Error() string { return e.msg } type ChainLinkError struct { msg string } func (c ChainLinkError) Error() string { return fmt.Sprintf("Error in parsing chain Link: %s", c.msg) } type ChainLinkStubbedUnsupportedError struct { msg string } func (c ChainLinkStubbedUnsupportedError) Error() string { return c.msg } type SigchainV2Error struct { msg string } func (s SigchainV2Error) Error() string { return fmt.Sprintf("Error in sigchain v2 link: %s", s.msg) } type SigchainV2MismatchedFieldError struct { msg string } func (s SigchainV2MismatchedFieldError) Error() string { return fmt.Sprintf("Mismatched field in sigchain v2 link: %s", s.msg) } type SigchainV2StubbedFirstLinkError struct{} func (s SigchainV2StubbedFirstLinkError) Error() string { return "First link can't be stubbed out" } type SigchainV2StubbedSignatureNeededError struct{} func (s SigchainV2StubbedSignatureNeededError) Error() string { return "Stubbed-out link actually needs a signature" } type SigchainV2MismatchedHashError struct{} func (s SigchainV2MismatchedHashError) Error() string { return "Sigchain V2 hash mismatch error" } type SigchainV2StubbedDisallowed struct{} func (s SigchainV2StubbedDisallowed) Error() string { return "Link was stubbed but required" } type SigchainV2Required struct{} func (s SigchainV2Required) Error() string { return "Link must use sig v2" } // ============================================================================= type ReverseSigError struct { msg string } func (r ReverseSigError) Error() string { return fmt.Sprintf("Error in reverse signature: %s", r.msg) } func NewReverseSigError(msgf string, a ...any) ReverseSigError { return ReverseSigError{msg: fmt.Sprintf(msgf, a...)} } // ============================================================================= type ConfigError struct { fn string msg string } func (c ConfigError) Error() string { return fmt.Sprintf("In config file %s: %s\n", c.fn, c.msg) } // ============================================================================= type NoUserConfigError struct{} func (n NoUserConfigError) Error() string { return "No user config found for user" } // ============================================================================= type InactiveKeyError struct { kid keybase1.KID } func (i InactiveKeyError) Error() string { return fmt.Sprintf("The key '%s' is not active", i.kid) } // ============================================================================= type merkleClientErrorType int const ( merkleErrorNone merkleClientErrorType = iota merkleErrorNoKnownKey merkleErrorNoLegacyUIDRoot merkleErrorUIDMismatch merkleErrorNoSkipSequence merkleErrorSkipMissing merkleErrorSkipHashMismatch merkleErrorHashMeta merkleErrorBadResetChain merkleErrorNotFound merkleErrorBadSeqno merkleErrorBadLeaf merkleErrorNoUpdates merkleErrorBadSigID merkleErrorAncientSeqno merkleErrorKBFSBadTree merkleErrorKBFSMismatch merkleErrorBadRoot merkleErrorOldTree merkleErrorOutOfOrderCtime merkleErrorWrongSkipSequence merkleErrorWrongRootSkips merkleErrorFailedCheckpoint merkleErrorTooMuchClockDrift ) type MerkleClientError struct { m string t merkleClientErrorType } func NewClientMerkleSkipHashMismatchError(m string) MerkleClientError { return MerkleClientError{ t: merkleErrorSkipHashMismatch, m: m, } } func NewClientMerkleSkipMissingError(m string) MerkleClientError { return MerkleClientError{ t: merkleErrorSkipMissing, m: m, } } func NewClientMerkleFailedCheckpointError(m string) MerkleClientError { return MerkleClientError{ t: merkleErrorFailedCheckpoint, m: m, } } func (m MerkleClientError) Error() string { return fmt.Sprintf("Error checking merkle tree: %s", m.m) } func (m MerkleClientError) IsNotFound() bool { return m.t == merkleErrorNotFound } func (m MerkleClientError) IsOldTree() bool { return m.t == merkleErrorOldTree } func (m MerkleClientError) IsSkipHashMismatch() bool { return m.t == merkleErrorSkipHashMismatch } type MerklePathNotFoundError struct { k string msg string } func (m MerklePathNotFoundError) Error() string { return fmt.Sprintf("For key '%s', Merkle path not found: %s", m.k, m.msg) } type MerkleClashError struct { c string } func (m MerkleClashError) Error() string { return fmt.Sprintf("Merkle tree clashed with server reply: %s", m.c) } // ============================================================================= type CanceledError struct { M string } func (c CanceledError) Error() string { return c.M } func NewCanceledError(m string) CanceledError { return CanceledError{M: m} } type InputCanceledError struct{} func (e InputCanceledError) Error() string { return "Input canceled" } type SkipSecretPromptError struct{} func (e SkipSecretPromptError) Error() string { return "Skipping secret prompt due to recent user cancel of secret prompt" } // ============================================================================= type NoDeviceError struct { Reason string } func NewNoDeviceError(s string) NoDeviceError { return NoDeviceError{s} } func (e NoDeviceError) Error() string { return fmt.Sprintf("No device found %s", e.Reason) } type TimeoutError struct{} func (e TimeoutError) Error() string { return "Operation timed out" } type ReceiverDeviceError struct { Msg string } func NewReceiverDeviceError(expected, received keybase1.DeviceID) ReceiverDeviceError { return ReceiverDeviceError{Msg: fmt.Sprintf("Device ID mismatch in message receiver, got %q, expected %q", received, expected)} } func (e ReceiverDeviceError) Error() string { return e.Msg } type InvalidKexPhraseError struct{} func (e InvalidKexPhraseError) Error() string { return "Invalid kex secret phrase" } var ErrNilUser = errors.New("User is nil") // ============================================================================= type StreamExistsError struct{} func (s StreamExistsError) Error() string { return "stream already exists" } type StreamNotFoundError struct{} func (s StreamNotFoundError) Error() string { return "stream wasn't found" } type StreamWrongKindError struct{} func (s StreamWrongKindError) Error() string { return "found a stream but not of right kind" } // ============================================================================= type UntrackError struct { err string } func (e UntrackError) Error() string { return fmt.Sprintf("Unfollow error: %s", e.err) } func NewUntrackError(d string, a ...any) UntrackError { return UntrackError{ err: fmt.Sprintf(d, a...), } } // ============================================================================= type APINetError struct { Err error } func (e APINetError) Error() string { return fmt.Sprintf("API network error: %s", e.Err) } func (e APINetError) Unwrap() error { return e.Err } // ============================================================================= type NoDecryptionKeyError struct { Msg string } func (e NoDecryptionKeyError) Error() string { return fmt.Sprintf("decrypt error: %s", e.Msg) } // ============================================================================= type ErrorCause struct { Err error StatusCode int } // DecryptionError is the default decryption error type DecryptionError struct { Cause ErrorCause } func (e DecryptionError) Error() string { if e.Cause.Err == nil { return "Decryption error" } return fmt.Sprintf("Decryption error: %+v", e.Cause) } func (e DecryptionError) Unwrap() error { return e.Cause.Err } // ============================================================================= // VerificationError is the default verification error type VerificationError struct { Cause ErrorCause } func (e VerificationError) Error() string { if e.Cause.Err == nil { return "Verification error" } return fmt.Sprintf("Verification error: %+v", e.Cause) } // ============================================================================= type ChainLinkPrevHashMismatchError struct { Msg string } func (e ChainLinkPrevHashMismatchError) Error() string { return fmt.Sprintf("Chain link prev hash mismatch error: %s", e.Msg) } // ============================================================================= type ChainLinkWrongSeqnoError struct { Msg string } func (e ChainLinkWrongSeqnoError) Error() string { return fmt.Sprintf("Chain link wrong seqno error: %s", e.Msg) } func NewChainLinkWrongSeqnoError(s string) error { return ChainLinkWrongSeqnoError{s} } // ============================================================================= type ChainLinkHighSkipHashMismatchError struct { Msg string } func (e ChainLinkHighSkipHashMismatchError) Error() string { return fmt.Sprintf("Chain link HighSkipHash mismatch error: %s", e.Msg) } // ============================================================================= type ChainLinkWrongHighSkipSeqnoError struct { Msg string } func (e ChainLinkWrongHighSkipSeqnoError) Error() string { return fmt.Sprintf("Chain link wrong HighSkipSeqno error: %s", e.Msg) } // ============================================================================= type CtimeMismatchError struct { Msg string } func (e CtimeMismatchError) Error() string { return fmt.Sprintf("Ctime mismatch error: %s", e.Msg) } // ============================================================================= type ChainLinkFingerprintMismatchError struct { Msg string } func (e ChainLinkFingerprintMismatchError) Error() string { return e.Msg } // ============================================================================= type ChainLinkKIDMismatchError struct { Msg string } func (e ChainLinkKIDMismatchError) Error() string { return e.Msg } // ============================================================================= type UnknownSpecialKIDError struct { k keybase1.KID } func (u UnknownSpecialKIDError) Error() string { return fmt.Sprintf("Unknown special KID: %s", u.k) } type IdentifyTimeoutError struct{} func (e IdentifyTimeoutError) Error() string { return "Identification expired." } // ============================================================================= type TrackBrokenError struct{} func (e TrackBrokenError) Error() string { return "track of user was broken" } // ============================================================================= type IdentifyDidNotCompleteError struct{} func (e IdentifyDidNotCompleteError) Error() string { return "Identification did not complete." } // ============================================================================= type IdentifyFailedError struct { Assertion string Reason string } func (e IdentifyFailedError) Error() string { return fmt.Sprintf("For user %q: %s", e.Assertion, e.Reason) } // ============================================================================= type IdentifiesFailedError struct{} func (e IdentifiesFailedError) Error() string { return "one or more identifies failed" } func NewIdentifiesFailedError() IdentifiesFailedError { return IdentifiesFailedError{} } // ============================================================================= type IdentifySummaryError struct { username NormalizedUsername problems []string } func NewIdentifySummaryError(failure keybase1.TLFIdentifyFailure) IdentifySummaryError { problem := "a followed proof failed" if failure.Breaks != nil { num := len(failure.Breaks.Proofs) problem = fmt.Sprintf("%d followed proof%s failed", num, GiveMeAnS(num)) } return IdentifySummaryError{ username: NewNormalizedUsername(failure.User.Username), problems: []string{problem}, } } func (e IdentifySummaryError) Error() string { return fmt.Sprintf("failed to identify %q: %s", e.username, strings.Join(e.problems, "; ")) } func (e IdentifySummaryError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_IDENTIFY, true } func (e IdentifySummaryError) Problems() []string { return e.problems } func IsIdentifyProofError(err error) bool { var pe ProofError var ise IdentifySummaryError return errors.As(err, &pe) || errors.As(err, &ise) } // ============================================================================= type NotLatestSubchainError struct { Msg string } func (e NotLatestSubchainError) Error() string { return e.Msg } type LoginSessionNotFound struct { SessionID int } func (e LoginSessionNotFound) Error() string { return fmt.Sprintf("No login session found for session id %d", e.SessionID) } type KeyVersionError struct{} func (k KeyVersionError) Error() string { return "Invalid key version" } // ============================================================================= type PIDFileLockError struct { Filename string } func (e PIDFileLockError) Error() string { return fmt.Sprintf("error locking %s: server already running", e.Filename) } type SecretStoreError struct { Msg string } func (e SecretStoreError) Error() string { return "Secret store error: " + e.Msg } type PassphraseProvisionImpossibleError struct{} func (e PassphraseProvisionImpossibleError) Error() string { return "Passphrase provision is not possible since you have at least one provisioned device or pgp key already" } type ProvisionViaDeviceRequiredError struct{} func (e ProvisionViaDeviceRequiredError) Error() string { return "You must select an existing device to provision a new device" } type ProvisionUnavailableError struct{} func (e ProvisionUnavailableError) Error() string { return "Provision unavailable as you don't have access to any of your devices" } type InvalidArgumentError struct { Msg string } func (e InvalidArgumentError) Error() string { return fmt.Sprintf("invalid argument: %s", e.Msg) } type RetryExhaustedError struct{} func (e RetryExhaustedError) Error() string { return "Prompt attempts exhausted." } // ============================================================================= type PGPPullLoggedOutError struct{} func (e PGPPullLoggedOutError) Error() string { return "When running `pgp pull` logged out, you must specify users to pull keys for" } // ============================================================================= type UIDelegationUnavailableError struct{} func (e UIDelegationUnavailableError) Error() string { return "This process does not support UI delegation" } // ============================================================================= type UnmetAssertionError struct { User string Remote bool } func (e UnmetAssertionError) Error() string { which := "local" if e.Remote { which = "remote" } return fmt.Sprintf("Unmet %s assertions for user %q", which, e.User) } // ============================================================================= type ResolutionErrorKind int const ( ResolutionErrorGeneral ResolutionErrorKind = iota ResolutionErrorNotFound ResolutionErrorAmbiguous ResolutionErrorRateLimited ResolutionErrorInvalidInput ResolutionErrorRequestFailed ) type ResolutionError struct { Input string Msg string Kind ResolutionErrorKind } func (e ResolutionError) Error() string { return fmt.Sprintf("In resolving '%s': %s", e.Input, e.Msg) } func IsResolutionError(err error) bool { var re ResolutionError return errors.As(err, &re) } func IsResolutionNotFoundError(err error) bool { var rerr ResolutionError if !errors.As(err, &rerr) { return false } return rerr.Kind == ResolutionErrorNotFound } // ============================================================================= type NoUIDError struct{} func (e NoUIDError) Error() string { return "No UID given but one was expected" } // ============================================================================= type TrackingBrokeError struct{} func (e TrackingBrokeError) Error() string { return "Following broke" } // ============================================================================= type KeybaseSaltpackError struct{} func (e KeybaseSaltpackError) Error() string { return "Bad use of saltpack for Keybase" } // ============================================================================= type TrackStaleError struct { FirstTrack bool } func (e TrackStaleError) Error() string { return "Following statement was stale" } // ============================================================================= type InconsistentCacheStateError struct{} func (e InconsistentCacheStateError) Error() string { return "Inconsistent cache state, likely after a DB reset; need a force reload" } // ============================================================================= type UnknownStreamError struct{} func (e UnknownStreamError) Error() string { return "unknown stream format" } type UTF16UnsupportedError struct{} func (e UTF16UnsupportedError) Error() string { return "UTF-16 not supported" } type WrongCryptoFormatError struct { Wanted, Received CryptoMessageFormat Operation string } func (e WrongCryptoFormatError) Error() string { ret := "Wrong crypto message format" switch { case e.Wanted == CryptoMessageFormatPGP && e.Received == CryptoMessageFormatSaltpack: ret += "; wanted PGP but got saltpack" if len(e.Operation) > 0 { ret += "; try `keybase " + e.Operation + "` instead" } case e.Wanted == CryptoMessageFormatSaltpack && e.Received == CryptoMessageFormatPGP: ret += "; wanted saltpack but got PGP" if len(e.Operation) > 0 { ret += "; try `keybase pgp " + e.Operation + "` instead" } } return ret } // ============================================================================= type BadInvitationCodeError struct{} func (e BadInvitationCodeError) Error() string { return "bad invitation code" } type NoMatchingGPGKeysError struct { Fingerprints []string HasActiveDevice bool // true if the user has an active device that they chose not to use } func (e NoMatchingGPGKeysError) Error() string { return fmt.Sprintf("No private GPG keys found on this device that match account PGP keys %s", strings.Join(e.Fingerprints, ", ")) } type DeviceAlreadyProvisionedError struct{} func (e DeviceAlreadyProvisionedError) Error() string { return "Device already provisioned for current user" } type DirExecError struct { Path string } func (e DirExecError) Error() string { return fmt.Sprintf("file %q is a directory and not executable", e.Path) } type FileExecError struct { Path string } func (e FileExecError) Error() string { return fmt.Sprintf("file %q is not executable", e.Path) } func IsExecError(err error) bool { if err == nil { return false } var dirExecErr DirExecError var fileExecErr FileExecError var execErr *exec.Error var pathErr *os.PathError return errors.As(err, &dirExecErr) || errors.As(err, &fileExecErr) || errors.As(err, &execErr) || errors.As(err, &pathErr) } // ============================================================================= type UserDeletedError struct { Msg string } func (e UserDeletedError) Error() string { if len(e.Msg) == 0 { return "User deleted" } return e.Msg } // ============================================================================= type DeviceNameInUseError struct{} func (e DeviceNameInUseError) Error() string { return "device name already in use" } // ============================================================================= type DeviceBadNameError struct{} func (e DeviceBadNameError) Error() string { return "device name is malformed" } // ============================================================================= type UnexpectedChatDataFromServer struct { Msg string } func (e UnexpectedChatDataFromServer) Error() string { return fmt.Sprintf("unexpected chat data from server: %s", e.Msg) } // ============================================================================= type ChatInternalError struct{} func (e ChatInternalError) Error() string { return "chat internal error" } // ============================================================================= type ChatConvExistsError struct { ConvID chat1.ConversationID } func (e ChatConvExistsError) Error() string { return fmt.Sprintf("conversation already exists: %s", e.ConvID) } // ============================================================================= type ChatMessageCollisionError struct { HeaderHash string } func (e ChatMessageCollisionError) Error() string { return fmt.Sprintf("a message with that hash already exists: %s", e.HeaderHash) } // ============================================================================= type ChatCollisionError struct{} func (e ChatCollisionError) Error() string { return "conversation id collision" } // ============================================================================= type ChatUnknownTLFIDError struct { TlfID chat1.TLFID } func (e ChatUnknownTLFIDError) Error() string { return fmt.Sprintf("unknown TLF ID: %s", hex.EncodeToString(e.TlfID)) } // ============================================================================= type ChatNotInConvError struct { UID gregor.UID ConvID chat1.ConversationID } func (e ChatNotInConvError) Error() string { return fmt.Sprintf("user is not in conversation: %s uid: %s", e.ConvID.String(), e.UID.String()) } func (e ChatNotInConvError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_MISC, true } // ============================================================================= type ChatNotInTeamError struct { UID gregor.UID TlfID chat1.TLFID } func (e ChatNotInTeamError) Error() string { return fmt.Sprintf("user is not in team: %v uid: %s", e.TlfID, e.UID.String()) } func (e ChatNotInTeamError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_MISC, true } // ============================================================================= type ChatBadMsgError struct { Msg string } func (e ChatBadMsgError) Error() string { return e.Msg } func (e ChatBadMsgError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_MISC, true } // ============================================================================= type ChatBroadcastError struct { Msg string } func (e ChatBroadcastError) Error() string { return e.Msg } // ============================================================================= type ChatRateLimitError struct { Msg string RateLimit chat1.RateLimit } func (e ChatRateLimitError) Error() string { return e.Msg } // ============================================================================= type ChatAlreadySupersededError struct { Msg string } func (e ChatAlreadySupersededError) Error() string { return e.Msg } func (e ChatAlreadySupersededError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_MISC, true } // ============================================================================= type ChatAlreadyDeletedError struct { Msg string } func (e ChatAlreadyDeletedError) Error() string { return e.Msg } func (e ChatAlreadyDeletedError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_ALREADY_DELETED, true } // ============================================================================= type ChatBadConversationError struct { Msg string ConvID chat1.ConversationID } func (e ChatBadConversationError) Error() string { return e.Msg } func (e ChatBadConversationError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_MISC, true } // ============================================================================= type ChatTLFFinalizedError struct { TlfID chat1.TLFID } func (e ChatTLFFinalizedError) Error() string { return fmt.Sprintf("unable to create conversation on finalized TLF: %s", e.TlfID) } // ============================================================================= type ChatDuplicateMessageError struct { OutboxID chat1.OutboxID } func (e ChatDuplicateMessageError) Error() string { return fmt.Sprintf("duplicate message send: outboxID: %s", e.OutboxID) } func (e ChatDuplicateMessageError) IsImmediateFail() (chat1.OutboxErrorType, bool) { return chat1.OutboxErrorType_DUPLICATE, true } // ============================================================================= type ChatClientError struct { Msg string } func (e ChatClientError) Error() string { return fmt.Sprintf("error from chat server: %s", e.Msg) } func (e ChatClientError) IsImmediateFail() (chat1.OutboxErrorType, bool) { if strings.HasPrefix(e.Msg, "Admins have set that you must be a team") { return chat1.OutboxErrorType_MINWRITER, true } return chat1.OutboxErrorType_MISC, true } // ============================================================================= type ChatUsersAlreadyInConversationError struct { Uids []keybase1.UID } func (e ChatUsersAlreadyInConversationError) Error() string { return "Cannot readd existing users to this conversation" } // ============================================================================= type ChatStalePreviousStateError struct{} func (e ChatStalePreviousStateError) Error() string { return "Unable to change chat channels" } // ============================================================================= type ChatEphemeralRetentionPolicyViolatedError struct { MaxAge gregor1.DurationSec } func (e ChatEphemeralRetentionPolicyViolatedError) Error() string { return fmt.Sprintf("messages in this conversation are required to be exploding with a maximum lifetime of %v", e.MaxAge.ToDuration()) } // ============================================================================= type InvalidAddressError struct { Msg string } func (e InvalidAddressError) Error() string { return e.Msg } type ExistsError struct { Msg string } func (e ExistsError) Error() string { return e.Msg } // ============================================================================= type LevelDBOpenClosedError struct{} func (e LevelDBOpenClosedError) Error() string { return "opening a closed DB" } // ============================================================================= type DBError struct { Msg string } func (e DBError) Error() string { return fmt.Sprintf("DB error: %s", e.Msg) } func NewDBError(s string) DBError { return DBError{Msg: s} } // ============================================================================= // These rekey types are not-exact duplicates of the libkbfs errors of the same name. // NeedSelfRekeyError indicates that the folder in question needs to // be rekeyed for the local device, and can be done so by one of the // other user's devices. type NeedSelfRekeyError struct { // Canonical tlf name Tlf string Msg string } func (e NeedSelfRekeyError) Error() string { return e.Msg } // NeedOtherRekeyError indicates that the folder in question needs to // be rekeyed for the local device, and can only done so by one of the // other users. type NeedOtherRekeyError struct { // Canonical tlf name Tlf string Msg string } func (e NeedOtherRekeyError) Error() string { return e.Msg } // ============================================================================= type DeviceNotFoundError struct { Where string ID keybase1.DeviceID Loaded bool } func (e DeviceNotFoundError) Error() string { loaded := "" if !e.Loaded { loaded = " (no device keys loaded)" } return fmt.Sprintf("%s: no device found for ID=%s%s", e.Where, e.ID, loaded) } // ============================================================================= // PseudonymGetError is sometimes written by unmarshaling (no fields of) a server response. type PseudonymGetError struct { msg string } func (e PseudonymGetError) Error() string { if e.msg == "" { return "Pseudonym could not be resolved" } return e.msg } var _ error = (*PseudonymGetError)(nil) // ============================================================================= // PseudonymGetError is sometimes written by unmarshaling (some fields of) a server response. type KeyPseudonymGetError struct { msg string } func (e KeyPseudonymGetError) Error() string { if e.msg == "" { return "Pseudonym could not be resolved" } return e.msg } var _ error = (*KeyPseudonymGetError)(nil) // ============================================================================= type PerUserKeyImportError struct { msg string } func (e PerUserKeyImportError) Error() string { return fmt.Sprintf("per-user-key import error: %s", e.msg) } func NewPerUserKeyImportError(format string, args ...any) PerUserKeyImportError { return PerUserKeyImportError{ msg: fmt.Sprintf(format, args...), } } // ============================================================================= type LoginOfflineError struct { msg string } func NewLoginOfflineError(msg string) LoginOfflineError { return LoginOfflineError{msg: msg} } func (e LoginOfflineError) Error() string { return "LoginOffline error: " + e.msg } // ============================================================================= type EldestSeqnoMissingError struct{} func (e EldestSeqnoMissingError) Error() string { return "user's eldest seqno has not been loaded" } // ============================================================================= type AccountResetError struct { expected keybase1.UserVersion received keybase1.Seqno } func NewAccountResetError(uv keybase1.UserVersion, r keybase1.Seqno) AccountResetError { return AccountResetError{expected: uv, received: r} } func (e AccountResetError) Error() string { if e.received == keybase1.Seqno(0) { return fmt.Sprintf("Account reset, and not reestablished (for user %s)", e.expected.String()) } return fmt.Sprintf("Account reset, reestablished at %d (for user %s)", e.received, e.expected.String()) } type BadSessionError struct { Desc string } func (e BadSessionError) Error() string { return fmt.Sprintf("bad session: %s", e.Desc) } // BadClockError is returned when the server rejects a NIST because the // client's clock is too far from the server's (outside the plausibility // window). A NIST signs the client's local time, so every regenerated token // fails identically until the user fixes their clock; treating this as a // terminal (non-retryable) auth error prevents a tight reconnect/auth loop. type BadClockError struct { Desc string } func (e BadClockError) Error() string { return fmt.Sprintf("bad clock: %s", e.Desc) } type LoginStateTimeoutError struct { ActiveRequest string AttemptedRequest string Duration time.Duration } func (e LoginStateTimeoutError) Error() string { return fmt.Sprintf("LoginState request timeout - attempted: %s, active request: %s, duration: %s", e.ActiveRequest, e.AttemptedRequest, e.Duration) } type KBFSNotRunningError struct{} func (e KBFSNotRunningError) Error() string { const err string = "Keybase services aren't running - KBFS client not found." switch runtime.GOOS { case "linux": return fmt.Sprintf("%s On Linux you need to start them after an update with `run_keybase` command.", err) default: return err } } type RevokeCurrentDeviceError struct{} func (e RevokeCurrentDeviceError) Error() string { return "cannot revoke the current device without confirmation" } type RevokeLastDeviceError struct{ NoPassphrase bool } func (e RevokeLastDeviceError) Error() string { if e.NoPassphrase { return "cannot revoke the last device; set a passphrase first" } return "cannot revoke the last device in your account without confirmation" } // users with PGP keys who try to revoke last device get this: type RevokeLastDevicePGPError struct{} func (e RevokeLastDevicePGPError) Error() string { return "You cannot revoke the last device in your account. You can reset your account here: keybase.io/#account-reset" } // ============================================================================= type ImplicitTeamDisplayNameError struct { msg string } func (e ImplicitTeamDisplayNameError) Error() string { return fmt.Sprintf("Error parsing implicit team name: %s", e.msg) } func NewImplicitTeamDisplayNameError(format string, args ...any) ImplicitTeamDisplayNameError { return ImplicitTeamDisplayNameError{fmt.Sprintf(format, args...)} } type TeamVisibilityError struct { wantedPublic bool gotPublic bool } func (e TeamVisibilityError) Error() string { pps := func(public bool) string { if public { return "public" } return "private" } return fmt.Sprintf("loaded for %v team but got %v team", pps(e.wantedPublic), pps(e.gotPublic)) } func NewTeamVisibilityError(wantedPublic, gotPublic bool) TeamVisibilityError { return TeamVisibilityError{wantedPublic: wantedPublic, gotPublic: gotPublic} } type KeyMaskNotFoundError struct { App keybase1.TeamApplication Gen keybase1.PerTeamKeyGeneration } func (e KeyMaskNotFoundError) Error() string { msg := fmt.Sprintf("You don't have access to %s for this team", e.App) if e.Gen != keybase1.PerTeamKeyGeneration(0) { msg += fmt.Sprintf(" (at generation %d)", int(e.Gen)) } return msg } type ProvisionFailedOfflineError struct{} func (e ProvisionFailedOfflineError) Error() string { return "Device provisioning failed because the device is offline" } // ============================================================================= func UserErrorFromStatus(s keybase1.StatusCode) error { switch s { case keybase1.StatusCode_SCOk: return nil case keybase1.StatusCode_SCDeleted: return UserDeletedError{} default: return &APIError{Code: int(s), Msg: "user status error"} } } // ============================================================================= // InvalidRepoNameError indicates that a repo name is invalid. type InvalidRepoNameError struct { Name string } func (e InvalidRepoNameError) Error() string { return fmt.Sprintf("Invalid repo name %q", e.Name) } // ============================================================================= // RepoAlreadyCreatedError is returned when trying to create a repo // that already exists. type RepoAlreadyExistsError struct { DesiredName string ExistingName string ExistingID string } func (e RepoAlreadyExistsError) Error() string { return fmt.Sprintf( "A repo named %s (id=%s) already existed when trying to create "+ "a repo named %s", e.ExistingName, e.ExistingID, e.DesiredName) } // ============================================================================= // RepoDoesntExistError is returned when trying to delete a repo that doesn't exist. type RepoDoesntExistError struct { Name string } func (e RepoDoesntExistError) Error() string { return fmt.Sprintf("There is no repo named %q.", e.Name) } // ============================================================================= // NoOpError is returned when an RPC call is issued but it would // result in no change, so the call is dropped. type NoOpError struct { Desc string } func (e NoOpError) Error() string { return e.Desc } // ============================================================================= type NoSpaceOnDeviceError struct { Desc string } func (e NoSpaceOnDeviceError) Error() string { return e.Desc } // ============================================================================= type TeamInviteBadTokenError struct{} func (e TeamInviteBadTokenError) Error() string { return "invalid team invite token" } // ============================================================================= type TeamWritePermDeniedError struct{} func (e TeamWritePermDeniedError) Error() string { return "permission denied to modify team" } // ============================================================================= type TeamInviteTokenReusedError struct{} func (e TeamInviteTokenReusedError) Error() string { return "team invite token already used" } // ============================================================================= type TeamBadMembershipError struct{} func (e TeamBadMembershipError) Error() string { return "cannot perform operation because not a member of the team" } // ============================================================================= type TeamProvisionalError struct { CanKey bool IsPublic bool PreResolveDisplayName string } func (e TeamProvisionalError) Error() string { ret := "team is provisional" if e.CanKey { ret += ", but the user can key" } else { ret += ", and the user cannot key" } return ret } func NewTeamProvisionalError(canKey bool, isPublic bool, dn string) error { return TeamProvisionalError{canKey, isPublic, dn} } // ============================================================================= type NoActiveDeviceError struct{} func (e NoActiveDeviceError) Error() string { return "no active device" } // ============================================================================= type NoTriplesecError struct{} func (e NoTriplesecError) Error() string { return "No Triplesec was available after prompt" } func NewNoTriplesecError() error { return NoTriplesecError{} } // ============================================================================= type HexWrongLengthError struct{ msg string } func NewHexWrongLengthError(msg string) HexWrongLengthError { return HexWrongLengthError{msg} } func (e HexWrongLengthError) Error() string { return e.msg } // ============================================================================= type EphemeralPairwiseMACsMissingUIDsError struct{ UIDs []keybase1.UID } func NewEphemeralPairwiseMACsMissingUIDsError(uids []keybase1.UID) EphemeralPairwiseMACsMissingUIDsError { return EphemeralPairwiseMACsMissingUIDsError{ UIDs: uids, } } func (e EphemeralPairwiseMACsMissingUIDsError) Error() string { return fmt.Sprintf("Missing %d uids from pairwise macs", len(e.UIDs)) } // ============================================================================= type RecipientNotFoundError struct { error } func NewRecipientNotFoundError(message string) error { return RecipientNotFoundError{ error: errors.New(message), } } // ============================================================================= type FeatureFlagError struct { msg string feature Feature } func NewFeatureFlagError(s string, f Feature) error { return FeatureFlagError{s, f} } func (f FeatureFlagError) Feature() Feature { return f.feature } func (f FeatureFlagError) Error() string { return fmt.Sprintf("Feature %q flagged off: %s", f.feature, f.msg) } var _ error = FeatureFlagError{} // ============================================================================= type UserReverifyNeededError struct { msg string } func NewUserReverifyNeededError(s string) error { return UserReverifyNeededError{s} } func (e UserReverifyNeededError) Error() string { return fmt.Sprintf("User green link error: %s", e.msg) } // ============================================================================= type OfflineError struct{} func NewOfflineError() error { return OfflineError{} } func (e OfflineError) Error() string { return "Offline, and no cached results found" } // ============================================================================= type VerboseError interface { Error() string Verbose() string } type InvalidStellarAccountIDError struct { details string } func NewInvalidStellarAccountIDError(details string) InvalidStellarAccountIDError { return InvalidStellarAccountIDError{ details: details, } } func (e InvalidStellarAccountIDError) Error() string { return "Invalid Stellar address." } func (e InvalidStellarAccountIDError) Verbose() string { return fmt.Sprintf("Invalid Stellar address: %s", e.details) } // ============================================================================= type ResetWithActiveDeviceError struct{} func (e ResetWithActiveDeviceError) Error() string { return "You cannot reset your account from a logged-in device." } // ============================================================================= type ResetMissingParamsError struct { msg string } func NewResetMissingParamsError(msg string) error { return ResetMissingParamsError{msg: msg} } func (e ResetMissingParamsError) Error() string { return e.msg } // ============================================================================ type ChainLinkBadUnstubError struct { msg string } func NewChainLinkBadUnstubError(s string) error { return ChainLinkBadUnstubError{s} } func (c ChainLinkBadUnstubError) Error() string { return c.msg } // ============================================================================ // AppOutdatedError indicates that an operation failed because the client does // not support some necessary feature and needs to be updated. type AppOutdatedError struct { cause error } func NewAppOutdatedError(cause error) AppOutdatedError { return AppOutdatedError{cause: cause} } func (e AppOutdatedError) Error() string { if e.cause != nil { return fmt.Sprintf("AppOutdatedError: %v", e.cause.Error()) } return "AppOutdatedError" } func (e AppOutdatedError) Unwrap() error { return e.cause } // ============================================================================ type PushSecretWithoutPasswordError struct { msg string } func NewPushSecretWithoutPasswordError(msg string) error { return PushSecretWithoutPasswordError{msg: msg} } func (e PushSecretWithoutPasswordError) Error() string { return e.msg } // HumanErrorer is an interface that errors can implement if they want to expose what went wrong to // humans, either via the CLI or via the electron interface. It sometimes happens that errors get // wrapped inside of other errors up a stack, and it's hard to know what to show the user. // This can help. type HumanErrorer interface { HumanError() error } // HumanError takes an error and returns the topmost human error that's in the error, maybe to export // to the CLI, KBFS, or Electron. It's a mashup of the pkg/errors Error() function, and also our // own desire to return the topmost HumanError. // // See https://github.com/pkg/errors/blob/master/errors.go for the original pkg/errors code func HumanError(err error) error { type causer interface { Cause() error } for err != nil { humanErrorer, ok := err.(HumanErrorer) if ok { tmp := humanErrorer.HumanError() if tmp != nil { return tmp } } cause, ok := err.(causer) if !ok { break } err = cause.Cause() } return err } // ============================================================================ type TeamContactSettingsBlockError struct { blockedUIDs []keybase1.UID blockedUsernames []NormalizedUsername } func (e TeamContactSettingsBlockError) BlockedUIDs() []keybase1.UID { return e.blockedUIDs } func (e TeamContactSettingsBlockError) BlockedUsernames() []NormalizedUsername { return e.blockedUsernames } func (e TeamContactSettingsBlockError) Error() string { var tmp []string for _, u := range e.blockedUsernames { tmp = append(tmp, u.String()) } return fmt.Sprintf("some users couldn't be contacted due to privacy settings (%s)", strings.Join(tmp, ",")) } func NewTeamContactSettingsBlockError(s *AppStatus) TeamContactSettingsBlockError { e := TeamContactSettingsBlockError{} for k, v := range s.Fields { switch k { case "uids": e.blockedUIDs = parseUIDsFromString(v) case "usernames": e.blockedUsernames = parseUsernamesFromString(v) } } return e } // parseUIDsFromString takes a comma-separate string of UIDs and returns an array of UIDs, // **ignoring any errors** since sometimes need to call this code on an error path. func parseUIDsFromString(s string) []keybase1.UID { tmp := strings.Split(s, ",") var res []keybase1.UID for _, elem := range tmp { u, err := keybase1.UIDFromString(elem) if err == nil { res = append(res, u) } } return res } // parseUsernamesFromString takes a string that's a comma-separated list of usernames and then // returns a slice of NormalizedUsernames after splitting them. Does no error checking. func parseUsernamesFromString(s string) []NormalizedUsername { tmp := strings.Split(s, ",") var res []NormalizedUsername for _, elem := range tmp { res = append(res, NewNormalizedUsername(elem)) } return res } // ============================================================================= type HiddenChainDataMissingError struct { note string } func (e HiddenChainDataMissingError) Error() string { return fmt.Sprintf("hidden chain data missing error: %s", e.note) } func NewHiddenChainDataMissingError(format string, args ...any) HiddenChainDataMissingError { return HiddenChainDataMissingError{fmt.Sprintf(format, args...)} } var _ error = HiddenChainDataMissingError{} type HiddenMerkleErrorType int const ( HiddenMerkleErrorNone HiddenMerkleErrorType = iota HiddenMerkleErrorInconsistentLeaf HiddenMerkleErrorInconsistentUncommittedSeqno HiddenMerkleErrorInvalidHiddenResponseType HiddenMerkleErrorInvalidLeafType HiddenMerkleErrorNoHiddenChainInLeaf HiddenMerkleErrorOldLinkNotYetCommitted HiddenMerkleErrorRollbackCommittedSeqno HiddenMerkleErrorRollbackUncommittedSeqno HiddenMerkleErrorServerWitholdingLinks HiddenMerkleErrorUnexpectedAbsenceProof ) type HiddenMerkleError struct { m string t HiddenMerkleErrorType } func NewHiddenMerkleError(t HiddenMerkleErrorType, format string, args ...any) HiddenMerkleError { return HiddenMerkleError{ t: t, m: fmt.Sprintf(format, args...), } } func (e HiddenMerkleError) ErrorType() HiddenMerkleErrorType { return e.t } func (e HiddenMerkleError) Error() string { return fmt.Sprintf("hidden merkle client error (type %v): %s", e.t, e.m) } var _ error = HiddenMerkleError{} func IsTooManyFilesError(err error) bool { return strings.Contains(strings.ToLower(err.Error()), "too many open files") }