github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/errors.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libkbfs
     6  
     7  import (
     8  	"fmt"
     9  	"time"
    10  
    11  	"github.com/keybase/client/go/kbfs/data"
    12  	"github.com/keybase/client/go/kbfs/idutil"
    13  	"github.com/keybase/client/go/kbfs/kbfsblock"
    14  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    15  	"github.com/keybase/client/go/kbfs/kbfsmd"
    16  	"github.com/keybase/client/go/kbfs/tlf"
    17  	"github.com/keybase/client/go/kbfs/tlfhandle"
    18  	kbname "github.com/keybase/client/go/kbun"
    19  	"github.com/keybase/client/go/protocol/keybase1"
    20  )
    21  
    22  // WrapError simply wraps an error in a fmt.Stringer interface, so
    23  // that it can be reported.
    24  type WrapError struct {
    25  	Err error
    26  }
    27  
    28  // String implements the fmt.Stringer interface for WrapError
    29  func (e WrapError) String() string {
    30  	return e.Err.Error()
    31  }
    32  
    33  // InvalidBlockRefError indicates an invalid block reference was
    34  // encountered.
    35  type InvalidBlockRefError struct {
    36  	ref data.BlockRef
    37  }
    38  
    39  func (e InvalidBlockRefError) Error() string {
    40  	return fmt.Sprintf("Invalid block ref %s", e.ref)
    41  }
    42  
    43  // InvalidPathError indicates an invalid path was encountered.
    44  type InvalidPathError struct {
    45  	p data.Path
    46  }
    47  
    48  // Error implements the error interface for InvalidPathError.
    49  func (e InvalidPathError) Error() string {
    50  	return fmt.Sprintf("Invalid path %s", e.p.DebugString())
    51  }
    52  
    53  // InvalidParentPathError indicates a path without a valid parent was
    54  // encountered.
    55  type InvalidParentPathError struct {
    56  	p data.Path
    57  }
    58  
    59  // Error implements the error interface for InvalidParentPathError.
    60  func (e InvalidParentPathError) Error() string {
    61  	return fmt.Sprintf("Path with invalid parent %s", e.p.DebugString())
    62  }
    63  
    64  // DirNotEmptyError indicates that the user tried to unlink a
    65  // subdirectory that was not empty.
    66  type DirNotEmptyError struct {
    67  	Name data.PathPartString
    68  }
    69  
    70  // Error implements the error interface for DirNotEmptyError
    71  func (e DirNotEmptyError) Error() string {
    72  	return fmt.Sprintf("Directory %s is not empty and can't be removed", e.Name)
    73  }
    74  
    75  // TlfAccessError that the user tried to perform an unpermitted
    76  // operation on a top-level folder.
    77  type TlfAccessError struct {
    78  	ID tlf.ID
    79  }
    80  
    81  // Error implements the error interface for TlfAccessError
    82  func (e TlfAccessError) Error() string {
    83  	return fmt.Sprintf("Operation not permitted on folder %s", e.ID)
    84  }
    85  
    86  // RenameAcrossDirsError indicates that the user tried to do an atomic
    87  // rename across directories.
    88  type RenameAcrossDirsError struct {
    89  	// ApplicationExecPath, if not empty, is the exec path of the application
    90  	// that issued the rename.
    91  	ApplicationExecPath string
    92  }
    93  
    94  // Error implements the error interface for RenameAcrossDirsError
    95  func (e RenameAcrossDirsError) Error() string {
    96  	return "Cannot rename across directories"
    97  }
    98  
    99  // WriteUnsupportedError indicates an error when trying to write a file
   100  type WriteUnsupportedError struct {
   101  	Filename string
   102  }
   103  
   104  // Error implements the error interface for WriteUnsupportedError
   105  func (e WriteUnsupportedError) Error() string {
   106  	return fmt.Sprintf("Writing to %s is unsupported", e.Filename)
   107  }
   108  
   109  // WriteToReadonlyNodeError indicates an error when trying to write a
   110  // node that's marked as read-only.
   111  type WriteToReadonlyNodeError struct {
   112  	Filename string
   113  }
   114  
   115  // Error implements the error interface for WriteToReadonlyNodeError
   116  func (e WriteToReadonlyNodeError) Error() string {
   117  	return fmt.Sprintf("%s is read-only and writes are not allowed", e.Filename)
   118  }
   119  
   120  // UnsupportedOpInUnlinkedDirError indicates an error when trying to
   121  // create a file.
   122  type UnsupportedOpInUnlinkedDirError struct {
   123  	Dirpath string
   124  }
   125  
   126  // Error implements the error interface for UnsupportedOpInUnlinkedDirError.
   127  func (e UnsupportedOpInUnlinkedDirError) Error() string {
   128  	return fmt.Sprintf(
   129  		"Operation is unsupported in unlinked directory %s", e.Dirpath)
   130  }
   131  
   132  // NewWriteUnsupportedError returns unsupported error trying to write a file
   133  func NewWriteUnsupportedError(filename string) error {
   134  	return WriteUnsupportedError{
   135  		Filename: filename,
   136  	}
   137  }
   138  
   139  // NeedSelfRekeyError indicates that the folder in question needs to
   140  // be rekeyed for the local device, and can be done so by one of the
   141  // other user's devices.
   142  type NeedSelfRekeyError struct {
   143  	Tlf tlf.CanonicalName
   144  	Err error
   145  }
   146  
   147  // Error implements the error interface for NeedSelfRekeyError
   148  func (e NeedSelfRekeyError) Error() string {
   149  	return fmt.Sprintf("This device does not yet have read access to "+
   150  		"directory %s, log into Keybase from one of your other "+
   151  		"devices to grant access: %+v",
   152  		tlfhandle.BuildCanonicalPathForTlfName(tlf.Private, e.Tlf), e.Err)
   153  }
   154  
   155  // ToStatus exports error to status
   156  func (e NeedSelfRekeyError) ToStatus() keybase1.Status {
   157  	kv := keybase1.StringKVPair{
   158  		Key:   "Tlf",
   159  		Value: string(e.Tlf),
   160  	}
   161  	return keybase1.Status{
   162  		Code:   int(keybase1.StatusCode_SCNeedSelfRekey),
   163  		Name:   "SC_NEED_SELF_REKEY",
   164  		Desc:   e.Error(),
   165  		Fields: []keybase1.StringKVPair{kv},
   166  	}
   167  }
   168  
   169  // NeedOtherRekeyError indicates that the folder in question needs to
   170  // be rekeyed for the local device, and can only done so by one of the
   171  // other users.
   172  type NeedOtherRekeyError struct {
   173  	Tlf tlf.CanonicalName
   174  	Err error
   175  }
   176  
   177  // Error implements the error interface for NeedOtherRekeyError
   178  func (e NeedOtherRekeyError) Error() string {
   179  	return fmt.Sprintf("This device does not yet have read access to "+
   180  		"directory %s, ask one of the other directory participants to "+
   181  		"log into Keybase to grant you access automatically: %+v",
   182  		tlfhandle.BuildCanonicalPathForTlfName(tlf.Private, e.Tlf), e.Err)
   183  }
   184  
   185  // ToStatus exports error to status
   186  func (e NeedOtherRekeyError) ToStatus() keybase1.Status {
   187  	kv := keybase1.StringKVPair{
   188  		Key:   "Tlf",
   189  		Value: string(e.Tlf),
   190  	}
   191  	return keybase1.Status{
   192  		Code:   int(keybase1.StatusCode_SCNeedOtherRekey),
   193  		Name:   "SC_NEED_OTHER_REKEY",
   194  		Desc:   e.Error(),
   195  		Fields: []keybase1.StringKVPair{kv},
   196  	}
   197  }
   198  
   199  // NotFileBlockError indicates that a file block was expected but a
   200  // block of a different type was found.
   201  //
   202  // ptr and branch should be filled in, but p may be empty.
   203  type NotFileBlockError struct {
   204  	ptr    data.BlockPointer
   205  	branch data.BranchName
   206  	p      data.Path
   207  }
   208  
   209  func (e NotFileBlockError) Error() string {
   210  	return fmt.Sprintf("The block at %s is not a file block (branch=%s, path=%s)", e.ptr, e.branch, e.p)
   211  }
   212  
   213  // NotDirBlockError indicates that a file block was expected but a
   214  // block of a different type was found.
   215  //
   216  // ptr and branch should be filled in, but p may be empty.
   217  type NotDirBlockError struct {
   218  	ptr    data.BlockPointer
   219  	branch data.BranchName
   220  	p      data.Path
   221  }
   222  
   223  func (e NotDirBlockError) Error() string {
   224  	return fmt.Sprintf("The block at %s is not a dir block (branch=%s, path=%s)", e.ptr, e.branch, e.p)
   225  }
   226  
   227  // NotFileError indicates that the user tried to perform a
   228  // file-specific operation on something that isn't a file.
   229  type NotFileError struct {
   230  	path data.Path
   231  }
   232  
   233  // Error implements the error interface for NotFileError
   234  func (e NotFileError) Error() string {
   235  	return fmt.Sprintf("%s is not a file (folder %s)", e.path, e.path.Tlf)
   236  }
   237  
   238  // NotDirError indicates that the user tried to perform a
   239  // dir-specific operation on something that isn't a directory.
   240  type NotDirError struct {
   241  	path data.Path
   242  }
   243  
   244  // Error implements the error interface for NotDirError
   245  func (e NotDirError) Error() string {
   246  	return fmt.Sprintf("%s is not a directory (folder %s)", e.path, e.path.Tlf)
   247  }
   248  
   249  // BlockDecodeError indicates that a block couldn't be decoded as
   250  // expected; probably it is the wrong type.
   251  type BlockDecodeError struct {
   252  	decodeErr error
   253  }
   254  
   255  // Error implements the error interface for BlockDecodeError
   256  func (e BlockDecodeError) Error() string {
   257  	return fmt.Sprintf("Decode error for a block: %v", e.decodeErr)
   258  }
   259  
   260  // BadCryptoError indicates that KBFS performed a bad crypto operation.
   261  type BadCryptoError struct {
   262  	ID kbfsblock.ID
   263  }
   264  
   265  // Error implements the error interface for BadCryptoError
   266  func (e BadCryptoError) Error() string {
   267  	return fmt.Sprintf("Bad crypto for block %v", e.ID)
   268  }
   269  
   270  // BadCryptoMDError indicates that KBFS performed a bad crypto
   271  // operation, specifically on a MD object.
   272  type BadCryptoMDError struct {
   273  	ID tlf.ID
   274  }
   275  
   276  // Error implements the error interface for BadCryptoMDError
   277  func (e BadCryptoMDError) Error() string {
   278  	return fmt.Sprintf("Bad crypto for the metadata of directory %v", e.ID)
   279  }
   280  
   281  // BadMDError indicates that the system is storing corrupt MD object
   282  // for the given TLF ID.
   283  type BadMDError struct {
   284  	ID tlf.ID
   285  }
   286  
   287  // Error implements the error interface for BadMDError
   288  func (e BadMDError) Error() string {
   289  	return fmt.Sprintf("Wrong format for metadata for directory %v", e.ID)
   290  }
   291  
   292  // MDMismatchError indicates an inconsistent or unverifiable MD object
   293  // for the given top-level folder.
   294  type MDMismatchError struct {
   295  	Revision kbfsmd.Revision
   296  	Dir      string
   297  	TlfID    tlf.ID
   298  	Err      error
   299  }
   300  
   301  // Error implements the error interface for MDMismatchError
   302  func (e MDMismatchError) Error() string {
   303  	return fmt.Sprintf("Could not verify metadata (revision=%d) for directory %s (id=%s): %s",
   304  		e.Revision, e.Dir, e.TlfID, e.Err)
   305  }
   306  
   307  // NoSuchMDError indicates that there is no MD object for the given
   308  // folder, revision, and merged status.
   309  type NoSuchMDError struct {
   310  	Tlf tlf.ID
   311  	Rev kbfsmd.Revision
   312  	BID kbfsmd.BranchID
   313  }
   314  
   315  // Error implements the error interface for NoSuchMDError
   316  func (e NoSuchMDError) Error() string {
   317  	return fmt.Sprintf("Couldn't get metadata for folder %v, revision %d, "+
   318  		"%s", e.Tlf, e.Rev, e.BID)
   319  }
   320  
   321  // InvalidDataVersionError indicates that an invalid data version was
   322  // used.
   323  type InvalidDataVersionError struct {
   324  	DataVer data.Ver
   325  }
   326  
   327  // Error implements the error interface for InvalidDataVersionError.
   328  func (e InvalidDataVersionError) Error() string {
   329  	return fmt.Sprintf("Invalid data version %d", int(e.DataVer))
   330  }
   331  
   332  // NewDataVersionError indicates that the data at the given path has
   333  // been written using a new data version that our client doesn't
   334  // understand.
   335  type NewDataVersionError struct {
   336  	path    data.Path
   337  	DataVer data.Ver
   338  }
   339  
   340  // Error implements the error interface for NewDataVersionError.
   341  func (e NewDataVersionError) Error() string {
   342  	return fmt.Sprintf(
   343  		"The data at path %s is of a version (%d) that we can't read "+
   344  			"(in folder %s)",
   345  		e.path, e.DataVer, e.path.Tlf)
   346  }
   347  
   348  // OutdatedVersionError indicates that we have encountered some new
   349  // data version we don't understand, and the user should be prompted
   350  // to upgrade.
   351  type OutdatedVersionError struct {
   352  }
   353  
   354  // Error implements the error interface for OutdatedVersionError.
   355  func (e OutdatedVersionError) Error() string {
   356  	return "Your software is out of date, and cannot read this data.  " +
   357  		"Please use `keybase update check` to upgrade your software."
   358  }
   359  
   360  // InvalidVersionError indicates that we have encountered some new data version
   361  // we don't understand, and we don't know how to handle it.
   362  type InvalidVersionError struct {
   363  	msg string
   364  }
   365  
   366  // Error implements the error interface for InvalidVersionError.
   367  func (e InvalidVersionError) Error() string {
   368  	if e.msg != "" {
   369  		return e.msg
   370  	}
   371  	return "The version provided is not valid."
   372  }
   373  
   374  // TooLowByteCountError indicates that size of a block is smaller than
   375  // the expected size.
   376  type TooLowByteCountError struct {
   377  	ExpectedMinByteCount int
   378  	ByteCount            int
   379  }
   380  
   381  // Error implements the error interface for TooLowByteCountError
   382  func (e TooLowByteCountError) Error() string {
   383  	return fmt.Sprintf("Expected at least %d bytes, got %d bytes",
   384  		e.ExpectedMinByteCount, e.ByteCount)
   385  }
   386  
   387  // InconsistentEncodedSizeError is raised when a dirty block has a
   388  // non-zero encoded size.
   389  type InconsistentEncodedSizeError struct {
   390  	info data.BlockInfo
   391  }
   392  
   393  // Error implements the error interface for InconsistentEncodedSizeError
   394  func (e InconsistentEncodedSizeError) Error() string {
   395  	return fmt.Sprintf("Block pointer to dirty block %v with non-zero "+
   396  		"encoded size = %d bytes", e.info.ID, e.info.EncodedSize)
   397  }
   398  
   399  // MDWriteNeededInRequest indicates that the system needs MD write
   400  // permissions to successfully complete an operation, so it should
   401  // retry in mdWrite mode.
   402  type MDWriteNeededInRequest struct {
   403  }
   404  
   405  // Error implements the error interface for MDWriteNeededInRequest
   406  func (e MDWriteNeededInRequest) Error() string {
   407  	return "This request needs MD write access, but doesn't have it."
   408  }
   409  
   410  // VerifyingKeyNotFoundError indicates that a verifying key matching
   411  // the given one couldn't be found.
   412  type VerifyingKeyNotFoundError struct {
   413  	key kbfscrypto.VerifyingKey
   414  }
   415  
   416  func (e VerifyingKeyNotFoundError) Error() string {
   417  	return fmt.Sprintf("Could not find verifying key %s", e.key)
   418  }
   419  
   420  // UnverifiableTlfUpdateError indicates that a MD update could not be
   421  // verified.
   422  type UnverifiableTlfUpdateError struct {
   423  	Tlf  string
   424  	User kbname.NormalizedUsername
   425  	Err  error
   426  }
   427  
   428  // Error implements the error interface for UnverifiableTlfUpdateError.
   429  func (e UnverifiableTlfUpdateError) Error() string {
   430  	return fmt.Sprintf("%s was last written by an unknown device claiming "+
   431  		"to belong to user %s.  The device has possibly been revoked by the "+
   432  		"user.  Use `keybase log send` to file an issue with the Keybase "+
   433  		"admins.", e.Tlf, e.User)
   434  }
   435  
   436  // KeyCacheMissError indicates that a key matching the given TLF ID
   437  // and key generation wasn't found in cache.
   438  type KeyCacheMissError struct {
   439  	tlf    tlf.ID
   440  	keyGen kbfsmd.KeyGen
   441  }
   442  
   443  // Error implements the error interface for KeyCacheMissError.
   444  func (e KeyCacheMissError) Error() string {
   445  	return fmt.Sprintf("Could not find key with tlf=%s, keyGen=%d", e.tlf, e.keyGen)
   446  }
   447  
   448  // KeyCacheHitError indicates that a key matching the given TLF ID
   449  // and key generation was found in cache but the object type was unknown.
   450  type KeyCacheHitError struct {
   451  	tlf    tlf.ID
   452  	keyGen kbfsmd.KeyGen
   453  }
   454  
   455  // Error implements the error interface for KeyCacheHitError.
   456  func (e KeyCacheHitError) Error() string {
   457  	return fmt.Sprintf("Invalid key with tlf=%s, keyGen=%d", e.tlf, e.keyGen)
   458  }
   459  
   460  // NoKeysError indicates that no keys were provided for a decryption allowing
   461  // multiple device keys
   462  type NoKeysError struct{}
   463  
   464  func (e NoKeysError) Error() string {
   465  	return "No keys provided"
   466  }
   467  
   468  // WrongOpsError indicates that an unexpected path got passed into a
   469  // FolderBranchOps instance
   470  type WrongOpsError struct {
   471  	nodeFB data.FolderBranch
   472  	opsFB  data.FolderBranch
   473  }
   474  
   475  // Error implements the error interface for WrongOpsError.
   476  func (e WrongOpsError) Error() string {
   477  	return fmt.Sprintf("Ops for folder %v, branch %s, was given path %s, "+
   478  		"branch %s", e.opsFB.Tlf, e.opsFB.Branch, e.nodeFB.Tlf, e.nodeFB.Branch)
   479  }
   480  
   481  // NodeNotFoundError indicates that we tried to find a node for the
   482  // given BlockPointer and failed.
   483  type NodeNotFoundError struct {
   484  	ptr data.BlockPointer
   485  }
   486  
   487  // Error implements the error interface for NodeNotFoundError.
   488  func (e NodeNotFoundError) Error() string {
   489  	return fmt.Sprintf("No node found for pointer %v", e.ptr)
   490  }
   491  
   492  // ParentNodeNotFoundError indicates that we tried to update a Node's
   493  // parent with a BlockPointer that we don't yet know about.
   494  type ParentNodeNotFoundError struct {
   495  	parent data.BlockRef
   496  }
   497  
   498  // Error implements the error interface for ParentNodeNotFoundError.
   499  func (e ParentNodeNotFoundError) Error() string {
   500  	return fmt.Sprintf("No such parent node found for %v", e.parent)
   501  }
   502  
   503  // EmptyNameError indicates that the user tried to use an empty name
   504  // for the given BlockRef.
   505  type EmptyNameError struct {
   506  	ref data.BlockRef
   507  }
   508  
   509  // Error implements the error interface for EmptyNameError.
   510  func (e EmptyNameError) Error() string {
   511  	return fmt.Sprintf("Cannot use empty name for %v", e.ref)
   512  }
   513  
   514  // KeyHalfMismatchError is returned when the key server doesn't return the expected key half.
   515  type KeyHalfMismatchError struct {
   516  	Expected kbfscrypto.TLFCryptKeyServerHalfID
   517  	Actual   kbfscrypto.TLFCryptKeyServerHalfID
   518  }
   519  
   520  // Error implements the error interface for KeyHalfMismatchError.
   521  func (e KeyHalfMismatchError) Error() string {
   522  	return fmt.Sprintf("Key mismatch, expected ID: %s, actual ID: %s",
   523  		e.Expected, e.Actual)
   524  }
   525  
   526  // MDServerDisconnected indicates the MDServer has been disconnected for clients waiting
   527  // on an update channel.
   528  type MDServerDisconnected struct {
   529  }
   530  
   531  // Error implements the error interface for MDServerDisconnected.
   532  func (e MDServerDisconnected) Error() string {
   533  	return "MDServer is disconnected"
   534  }
   535  
   536  // MDUpdateInvertError indicates that we tried to apply a revision that
   537  // was not the next in line.
   538  type MDUpdateInvertError struct {
   539  	rev  kbfsmd.Revision
   540  	curr kbfsmd.Revision
   541  }
   542  
   543  // Error implements the error interface for MDUpdateInvertError.
   544  func (e MDUpdateInvertError) Error() string {
   545  	return fmt.Sprintf("MD revision %d isn't next in line for our "+
   546  		"current revision %d while inverting", e.rev, e.curr)
   547  }
   548  
   549  // NotPermittedWhileDirtyError indicates that some operation failed
   550  // because of outstanding dirty files, and may be retried later.
   551  type NotPermittedWhileDirtyError struct {
   552  }
   553  
   554  // Error implements the error interface for NotPermittedWhileDirtyError.
   555  func (e NotPermittedWhileDirtyError) Error() string {
   556  	return "Not permitted while writes are dirty"
   557  }
   558  
   559  // NoChainFoundError indicates that a conflict resolution chain
   560  // corresponding to the given pointer could not be found.
   561  type NoChainFoundError struct {
   562  	ptr data.BlockPointer
   563  }
   564  
   565  // Error implements the error interface for NoChainFoundError.
   566  func (e NoChainFoundError) Error() string {
   567  	return fmt.Sprintf("No chain found for %v", e.ptr)
   568  }
   569  
   570  // DisallowedPrefixError indicates that the user attempted to create
   571  // an entry using a name with a disallowed prefix.
   572  type DisallowedPrefixError struct {
   573  	name   data.PathPartString
   574  	prefix string
   575  }
   576  
   577  // Error implements the error interface for DisallowedPrefixError.
   578  func (e DisallowedPrefixError) Error() string {
   579  	return fmt.Sprintf("Cannot create %s because it has the prefix %s",
   580  		e.name, e.prefix)
   581  }
   582  
   583  // DisallowedNameError indicates that the user attempted to create an
   584  // entry using a disallowed name.  It includes the plaintext name on
   585  // purpose, for clarity in the error message.
   586  type DisallowedNameError struct {
   587  	name string
   588  }
   589  
   590  // Error implements the error interface for DisallowedNameError.
   591  func (e DisallowedNameError) Error() string {
   592  	return fmt.Sprintf("Cannot create \"%s\" because it is a disallowed name",
   593  		e.name)
   594  }
   595  
   596  // NameTooLongError indicates that the user tried to write a directory
   597  // entry name that would be bigger than KBFS's supported size.
   598  type NameTooLongError struct {
   599  	name            string
   600  	maxAllowedBytes uint32
   601  }
   602  
   603  // Error implements the error interface for NameTooLongError.
   604  func (e NameTooLongError) Error() string {
   605  	return fmt.Sprintf("New directory entry name %s has more than the maximum "+
   606  		"allowed number of bytes (%d)", e.name, e.maxAllowedBytes)
   607  }
   608  
   609  // NoCurrentSessionExpectedError is the error text that will get
   610  // converted into a NoCurrentSessionError.
   611  var NoCurrentSessionExpectedError = "no current session"
   612  
   613  // RekeyPermissionError indicates that the user tried to rekey a
   614  // top-level folder in a manner inconsistent with their permissions.
   615  type RekeyPermissionError struct {
   616  	User kbname.NormalizedUsername
   617  	Dir  string
   618  }
   619  
   620  // Error implements the error interface for RekeyPermissionError
   621  func (e RekeyPermissionError) Error() string {
   622  	return fmt.Sprintf("%s is trying to rekey directory %s in a manner "+
   623  		"inconsistent with their role", e.User, e.Dir)
   624  }
   625  
   626  // NewRekeyPermissionError constructs a RekeyPermissionError for the given
   627  // directory and user.
   628  func NewRekeyPermissionError(
   629  	dir *tlfhandle.Handle, username kbname.NormalizedUsername) error {
   630  	dirname := dir.GetCanonicalPath()
   631  	return RekeyPermissionError{username, dirname}
   632  }
   633  
   634  // RekeyIncompleteError is returned when a rekey is partially done but
   635  // needs a writer to finish it.
   636  type RekeyIncompleteError struct{}
   637  
   638  func (e RekeyIncompleteError) Error() string {
   639  	return "Rekey did not complete due to insufficient user permissions"
   640  }
   641  
   642  // TimeoutError is just a replacement for context.DeadlineExceeded
   643  // with a more friendly error string.
   644  type TimeoutError struct {
   645  }
   646  
   647  func (e TimeoutError) Error() string {
   648  	return "Operation timed out"
   649  }
   650  
   651  // InvalidOpError is returned when an operation is called that isn't supported
   652  // by the current implementation.
   653  type InvalidOpError struct {
   654  	op string
   655  }
   656  
   657  func (e InvalidOpError) Error() string {
   658  	return fmt.Sprintf("Invalid operation: %s", e.op)
   659  }
   660  
   661  // NoSuchFolderListError indicates that the user tried to access a
   662  // subdirectory of /keybase that doesn't exist.
   663  type NoSuchFolderListError struct {
   664  	Name      string
   665  	NameToLog string
   666  	PrivName  string
   667  	PubName   string
   668  }
   669  
   670  // Error implements the error interface for NoSuchFolderListError
   671  func (e NoSuchFolderListError) Error() string {
   672  	return fmt.Sprintf("/keybase/%s is not a Keybase folder. "+
   673  		"All folders begin with /keybase/%s or /keybase/%s.",
   674  		e.NameToLog, e.PrivName, e.PubName)
   675  }
   676  
   677  // UnexpectedUnmergedPutError indicates that we tried to do an
   678  // unmerged put when that was disallowed.
   679  type UnexpectedUnmergedPutError struct {
   680  }
   681  
   682  // Error implements the error interface for UnexpectedUnmergedPutError
   683  func (e UnexpectedUnmergedPutError) Error() string {
   684  	return "Unmerged puts are not allowed"
   685  }
   686  
   687  // NoSuchTlfHandleError indicates we were unable to resolve a folder
   688  // ID to a folder handle.
   689  type NoSuchTlfHandleError struct {
   690  	ID tlf.ID
   691  }
   692  
   693  // Error implements the error interface for NoSuchTlfHandleError
   694  func (e NoSuchTlfHandleError) Error() string {
   695  	return fmt.Sprintf("Folder handle for %s not found", e.ID)
   696  }
   697  
   698  // NoSuchTlfIDError indicates we were unable to resolve a folder
   699  // handle to a folder ID.
   700  type NoSuchTlfIDError struct {
   701  	handle *tlfhandle.Handle
   702  }
   703  
   704  // Error implements the error interface for NoSuchTlfIDError
   705  func (e NoSuchTlfIDError) Error() string {
   706  	return fmt.Sprintf("Folder ID for %s not found",
   707  		e.handle.GetCanonicalPath())
   708  }
   709  
   710  // IncompatibleHandleError indicates that somethine tried to update
   711  // the head of a TLF with a RootMetadata with an incompatible handle.
   712  type IncompatibleHandleError struct {
   713  	oldName                  tlf.CanonicalName
   714  	partiallyResolvedOldName tlf.CanonicalName
   715  	newName                  tlf.CanonicalName
   716  }
   717  
   718  func (e IncompatibleHandleError) Error() string {
   719  	return fmt.Sprintf(
   720  		"old head %q resolves to %q instead of new head %q",
   721  		e.oldName, e.partiallyResolvedOldName, e.newName)
   722  }
   723  
   724  // UnmergedError indicates that fbo is on an unmerged local revision
   725  type UnmergedError struct {
   726  }
   727  
   728  // Error implements the error interface for UnmergedError.
   729  func (e UnmergedError) Error() string {
   730  	return "fbo is on an unmerged local revision"
   731  }
   732  
   733  // ExclOnUnmergedError happens when an operation with O_EXCL set when fbo is on
   734  // an unmerged local revision
   735  type ExclOnUnmergedError struct {
   736  }
   737  
   738  // Error implements the error interface for ExclOnUnmergedError.
   739  func (e ExclOnUnmergedError) Error() string {
   740  	return "an operation with O_EXCL set is called but fbo is on an unmerged local version"
   741  }
   742  
   743  // OverQuotaWarning indicates that the user is over their quota, and
   744  // is being slowed down by the server.
   745  type OverQuotaWarning struct {
   746  	UsageBytes int64
   747  	LimitBytes int64
   748  }
   749  
   750  // Error implements the error interface for OverQuotaWarning.
   751  func (w OverQuotaWarning) Error() string {
   752  	return fmt.Sprintf("You are using %d bytes, and your plan limits you "+
   753  		"to %d bytes.  Please delete some data.", w.UsageBytes, w.LimitBytes)
   754  }
   755  
   756  // OpsCantHandleFavorite means that folderBranchOps wasn't able to
   757  // deal with a favorites request.
   758  type OpsCantHandleFavorite struct {
   759  	Msg string
   760  }
   761  
   762  // Error implements the error interface for OpsCantHandleFavorite.
   763  func (e OpsCantHandleFavorite) Error() string {
   764  	return fmt.Sprintf("Couldn't handle the favorite operation: %s", e.Msg)
   765  }
   766  
   767  // RekeyConflictError indicates a conflict happened while trying to rekey.
   768  type RekeyConflictError struct {
   769  	Err error
   770  }
   771  
   772  // Error implements the error interface for RekeyConflictError.
   773  func (e RekeyConflictError) Error() string {
   774  	return fmt.Sprintf("Conflict during a rekey, not retrying: %v", e.Err)
   775  }
   776  
   777  // UnmergedSelfConflictError indicates that we hit a conflict on the
   778  // unmerged branch, so a previous MD PutUnmerged we thought had
   779  // failed, had actually succeeded.
   780  type UnmergedSelfConflictError struct {
   781  	Err error
   782  }
   783  
   784  // Error implements the error interface for UnmergedSelfConflictError.
   785  func (e UnmergedSelfConflictError) Error() string {
   786  	return fmt.Sprintf("Unmerged self conflict: %v", e.Err)
   787  }
   788  
   789  // blockNonExistentError is returned when a block doesn't exist. This
   790  // is a generic error, suitable for use by non-server types, whereas
   791  // kbfsblock.ServerErrorBlockNonExistent is used only by servers.
   792  type blockNonExistentError struct {
   793  	id kbfsblock.ID
   794  }
   795  
   796  func (e blockNonExistentError) Error() string {
   797  	return fmt.Sprintf("block %s does not exist", e.id)
   798  }
   799  
   800  // NoMergedMDError indicates that no MDs for this folder have been
   801  // created yet.
   802  type NoMergedMDError struct {
   803  	tlf tlf.ID
   804  }
   805  
   806  // Error implements the error interface for NoMergedMDError.
   807  func (e NoMergedMDError) Error() string {
   808  	return fmt.Sprintf("No MD yet for TLF %s", e.tlf)
   809  }
   810  
   811  // InvalidFavoritesOpError indicates an unknown FavoritesOp has been provided.
   812  type InvalidFavoritesOpError struct{}
   813  
   814  // Error implements the error interface for InvalidFavoritesOpError.
   815  func (InvalidFavoritesOpError) Error() string {
   816  	return "invalid FavoritesOp"
   817  }
   818  
   819  // DiskCacheClosedError indicates that the disk cache has been
   820  // closed, and thus isn't accepting any more operations.
   821  type DiskCacheClosedError struct {
   822  	op string
   823  }
   824  
   825  // Error implements the error interface for DiskCacheClosedError.
   826  func (e DiskCacheClosedError) Error() string {
   827  	return fmt.Sprintf("Error performing %s operation: the disk cache is "+
   828  		"closed", e.op)
   829  }
   830  
   831  // DiskCacheStartingError indicates that the disk cache has not yet started, so
   832  // it isn't yet accepting operations.
   833  type DiskCacheStartingError struct {
   834  	op string
   835  }
   836  
   837  // Error implements the error interface for DiskCacheStartingError.
   838  func (e DiskCacheStartingError) Error() string {
   839  	return fmt.Sprintf("Error performing %s operation: the disk cache is "+
   840  		"still starting", e.op)
   841  }
   842  
   843  // NoUpdatesWhileDirtyError indicates that updates aren't being
   844  // accepted while a TLF is locally dirty.
   845  type NoUpdatesWhileDirtyError struct{}
   846  
   847  // Error implements the error interface for NoUpdatesWhileDirtyError.
   848  func (e NoUpdatesWhileDirtyError) Error() string {
   849  	return "Ignoring MD updates while writes are dirty"
   850  }
   851  
   852  // Disk Cache Errors
   853  const (
   854  	// StatusCodeDiskBlockCacheError is a generic disk cache error.
   855  	StatusCodeDiskBlockCacheError = 0x666
   856  	// StatusCodeDiskMDCacheError is a generic disk cache error.
   857  	StatusCodeDiskMDCacheError = 0x667
   858  	// StatusCodeDiskQuotaCacheError is a generic disk cache error.
   859  	StatusCodeDiskQuotaCacheError = 0x668
   860  )
   861  
   862  // DiskBlockCacheError is a generic disk cache error.
   863  type DiskBlockCacheError struct {
   864  	Msg string
   865  }
   866  
   867  func newDiskBlockCacheError(err error) DiskBlockCacheError {
   868  	return DiskBlockCacheError{err.Error()}
   869  }
   870  
   871  // ToStatus implements the ExportableError interface for DiskBlockCacheError.
   872  func (e DiskBlockCacheError) ToStatus() (s keybase1.Status) {
   873  	s.Code = StatusCodeDiskBlockCacheError
   874  	s.Name = "DISK_BLOCK_CACHE_ERROR"
   875  	s.Desc = e.Msg
   876  	return
   877  }
   878  
   879  // Error implements the Error interface for DiskBlockCacheError.
   880  func (e DiskBlockCacheError) Error() string {
   881  	return "DiskBlockCacheError{" + e.Msg + "}"
   882  }
   883  
   884  // DiskMDCacheError is a generic disk cache error.
   885  type DiskMDCacheError struct {
   886  	Msg string
   887  }
   888  
   889  // ToStatus implements the ExportableError interface for DiskMDCacheError.
   890  func (e DiskMDCacheError) ToStatus() (s keybase1.Status) {
   891  	s.Code = StatusCodeDiskMDCacheError
   892  	s.Name = "DISK_MD_CACHE_ERROR"
   893  	s.Desc = e.Msg
   894  	return
   895  }
   896  
   897  // Error implements the Error interface for DiskMDCacheError.
   898  func (e DiskMDCacheError) Error() string {
   899  	return "DiskMDCacheError{" + e.Msg + "}"
   900  }
   901  
   902  // DiskQuotaCacheError is a generic disk cache error.
   903  type DiskQuotaCacheError struct {
   904  	Msg string
   905  }
   906  
   907  // ToStatus implements the ExportableError interface for DiskQuotaCacheError.
   908  func (e DiskQuotaCacheError) ToStatus() (s keybase1.Status) {
   909  	s.Code = StatusCodeDiskQuotaCacheError
   910  	s.Name = "DISK_QUOTA_CACHE_ERROR"
   911  	s.Desc = e.Msg
   912  	return
   913  }
   914  
   915  // Error implements the Error interface for DiskQuotaCacheError.
   916  func (e DiskQuotaCacheError) Error() string {
   917  	return "DiskQuotaCacheError{" + e.Msg + "}"
   918  }
   919  
   920  // RevokedDeviceVerificationError indicates that the user is trying to
   921  // verify a key that has been revoked.  It includes useful information
   922  // about the revocation, so the code receiving the error can check if
   923  // the device was valid at the time of the data being checked.
   924  type RevokedDeviceVerificationError struct {
   925  	info idutil.RevokedKeyInfo
   926  }
   927  
   928  // Error implements the Error interface for RevokedDeviceVerificationError.
   929  func (e RevokedDeviceVerificationError) Error() string {
   930  	return fmt.Sprintf("Device was revoked at time %s, root seqno %d",
   931  		e.info.Time.Time().Format(time.RFC3339Nano), e.info.MerkleRoot.Seqno)
   932  }
   933  
   934  // MDWrittenAfterRevokeError indicates that we failed to verify an MD
   935  // revision because it was written after the last valid revision that
   936  // the corresponding device could have written.
   937  type MDWrittenAfterRevokeError struct {
   938  	tlfID        tlf.ID
   939  	revBad       kbfsmd.Revision
   940  	revLimit     kbfsmd.Revision
   941  	verifyingKey kbfscrypto.VerifyingKey
   942  }
   943  
   944  // Error implements the Error interface for MDWrittenAfterRevokeError.
   945  func (e MDWrittenAfterRevokeError) Error() string {
   946  	return fmt.Sprintf("Failed to verify revision %d of folder %s by key %s; "+
   947  		"last valid revision would have been %d",
   948  		e.revBad, e.tlfID, e.verifyingKey, e.revLimit)
   949  }
   950  
   951  // RevGarbageCollectedError indicates that the user is trying to
   952  // access a revision that's already been garbage-collected.
   953  type RevGarbageCollectedError struct {
   954  	rev       kbfsmd.Revision
   955  	lastGCRev kbfsmd.Revision
   956  }
   957  
   958  // Error implements the Error interface for RevGarbageCollectedError.
   959  func (e RevGarbageCollectedError) Error() string {
   960  	return fmt.Sprintf("Requested revision %d has already been garbage "+
   961  		"collected (last GC'd rev=%d)", e.rev, e.lastGCRev)
   962  }
   963  
   964  // FolderNotResetOnServer indicates that a folder can't be reset by
   965  // the user, because it hasn't yet been reset on the mdserver.
   966  type FolderNotResetOnServer struct {
   967  	h *tlfhandle.Handle
   968  }
   969  
   970  // Error implements the Error interface for FolderNotResetOnServer.
   971  func (e FolderNotResetOnServer) Error() string {
   972  	return fmt.Sprintf("Folder %s is not yet reset on the server; "+
   973  		"contact Keybase for help", e.h.GetCanonicalPath())
   974  }
   975  
   976  // OfflineArchivedError indicates trying to access archived data while
   977  // offline.
   978  type OfflineArchivedError struct {
   979  	h *tlfhandle.Handle
   980  }
   981  
   982  // Error implements the Error interface for OfflineArchivedError.
   983  func (e OfflineArchivedError) Error() string {
   984  	return fmt.Sprintf("Archived data from %s is not available while offline",
   985  		e.h.GetCanonicalPath())
   986  }
   987  
   988  // OfflineUnsyncedError indicates trying to access unsynced data while
   989  // offline.
   990  type OfflineUnsyncedError struct {
   991  	h *tlfhandle.Handle
   992  }
   993  
   994  // Error implements the Error interface for OfflineUnsyncedError.
   995  func (e OfflineUnsyncedError) Error() string {
   996  	return fmt.Sprintf("Unsynced data from %s is not available while offline",
   997  		e.h.GetCanonicalPath())
   998  }
   999  
  1000  // NextMDNotCachedError indicates we haven't cached the next MD after
  1001  // the given Merkle seqno.
  1002  type NextMDNotCachedError struct {
  1003  	TlfID     tlf.ID
  1004  	RootSeqno keybase1.Seqno
  1005  }
  1006  
  1007  // Error implements the Error interface for NextMDNotCachedError.
  1008  func (e NextMDNotCachedError) Error() string {
  1009  	return fmt.Sprintf("The MD following %d for folder %s is not cached",
  1010  		e.RootSeqno, e.TlfID)
  1011  }
  1012  
  1013  // DiskCacheTooFullForBlockError indicates that the disk cache is too
  1014  // full to fetch a block requested with the `StopIfFull` action type.
  1015  type DiskCacheTooFullForBlockError struct {
  1016  	Ptr    data.BlockPointer
  1017  	Action BlockRequestAction
  1018  }
  1019  
  1020  // Error implements the Error interface for DiskCacheTooFullForBlockError.
  1021  func (e DiskCacheTooFullForBlockError) Error() string {
  1022  	return fmt.Sprintf(
  1023  		"Disk cache too full for block %s requested with action %s",
  1024  		e.Ptr, e.Action)
  1025  }
  1026  
  1027  // NonExistentTeamForHandleError indicates that we're trying to create
  1028  // a TLF for a handle that has no corresponding implicit team yet.
  1029  // Likely a writer needs to create the implicit team first.
  1030  type NonExistentTeamForHandleError struct {
  1031  	h *tlfhandle.Handle
  1032  }
  1033  
  1034  // Error implements the Error interface for NonExistentTeamForHandleError.
  1035  func (e NonExistentTeamForHandleError) Error() string {
  1036  	return fmt.Sprintf("Can't create TLF ID for non-team-backed handle %s",
  1037  		e.h.GetCanonicalPath())
  1038  }