github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/roachpb/errors.proto (about)

     1  // Copyright 2014 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  syntax = "proto2";
    12  package cockroach.roachpb;
    13  option go_package = "roachpb";
    14  
    15  import "roachpb/data.proto";
    16  import "roachpb/metadata.proto";
    17  import "util/hlc/timestamp.proto";
    18  import "gogoproto/gogo.proto";
    19  
    20  // Issue #1246. Commented out because
    21  // https://github.com/golang/protobuf/commit/d3d78384b82d449651d2435ed3
    22  // requires that all messages implement Message, which includes
    23  // `String() string`.
    24  // option (gogoproto.goproto_stringer_all) = false;
    25  
    26  // A NotLeaseHolderError indicates that the current range is not the lease
    27  // holder. If the lease holder is known, its Replica is set in the error.
    28  message NotLeaseHolderError {
    29    option (gogoproto.equal) = true;
    30  
    31    // The replica the error originated from. Used in the error's string
    32    // representation, if known.
    33    optional ReplicaDescriptor replica = 1 [(gogoproto.nullable) = false];
    34    // The lease holder, if known.
    35    optional ReplicaDescriptor lease_holder = 2;
    36    // The current lease, if known. This might be nil even when lease_holder is
    37    // set, as sometimes one can create this error without actually knowing the
    38    // current lease, but having a guess about who the leader is.
    39    optional Lease lease = 4;
    40    optional int64 range_id = 3 [(gogoproto.nullable) = false,
    41        (gogoproto.customname) = "RangeID", (gogoproto.casttype) = "RangeID"];
    42    // If set, the Error() method will return this instead of composing its
    43    // regular spiel. Useful because we reuse this error when rejecting a command
    44    // because the lease under which its application was attempted is different
    45    // than the lease under which it had been proposed.
    46    optional string custom_msg = 5 [(gogoproto.nullable) = false];
    47  }
    48  
    49  // A NodeUnavailableError indicates that the sending gateway can
    50  // not process requests at the time, and that the client should
    51  // retry the request with another peer.
    52  message NodeUnavailableError {
    53    option (gogoproto.equal) = true;
    54  }
    55  
    56  // An UnsupportedRequestError indicates that the recipient node
    57  // does not know how to handle the type of request received.
    58  message UnsupportedRequestError {
    59    option (gogoproto.equal) = true;
    60  }
    61  
    62  // A RangeNotFoundError indicates that a command was sent to a range
    63  // which is not hosted on this store.
    64  message RangeNotFoundError {
    65    option (gogoproto.equal) = true;
    66  
    67    optional int64 range_id = 1 [(gogoproto.nullable) = false,
    68        (gogoproto.customname) = "RangeID", (gogoproto.casttype) = "RangeID"];
    69    // store_id is nonzero only if the error originated on a Store.
    70    optional int64 store_id = 2 [(gogoproto.nullable) = false,
    71        (gogoproto.customname) = "StoreID", (gogoproto.casttype) = "StoreID"];
    72  }
    73  
    74  // A RangeKeyMismatchError indicates that a command was sent to a
    75  // range which did not contain the key(s) specified by the command.
    76  message RangeKeyMismatchError {
    77    option (gogoproto.equal) = true;
    78  
    79    optional bytes request_start_key = 1 [(gogoproto.casttype) = "Key"];
    80    optional bytes request_end_key = 2 [(gogoproto.casttype) = "Key"];
    81    // mismatched_range is the range that the command was incorrectly sent to.
    82    // It is used to update the sender's range cache without an additional range
    83    // lookup.
    84    optional RangeDescriptor mismatched_range = 3 [(gogoproto.nullable) = false];
    85    // suggested_range is a hint to the sender of a command about the range
    86    // they may be looking for. It is only populated when the recipient has
    87    // authoritative knowledge of the range requested by the sender.
    88    optional RangeDescriptor suggested_range = 4;
    89  }
    90  
    91  // A ReadWithinUncertaintyIntervalError indicates that a read at timestamp
    92  // encountered a write within the uncertainty interval of the reader.
    93  // The read should be retried at a higher timestamp; the timestamps contained
    94  // within are purely informational, though typically existing_timestamp is a
    95  // lower bound for a new timestamp at which at least the read producing
    96  // this error would succeed on retry.
    97  message ReadWithinUncertaintyIntervalError {
    98    option (gogoproto.equal) = true;
    99  
   100    // This data below is purely informational and used to tailor the
   101    // error message.
   102    optional util.hlc.Timestamp read_timestamp = 1 [(gogoproto.nullable) = false];
   103    optional util.hlc.Timestamp existing_timestamp = 2 [(gogoproto.nullable) = false];
   104    // The remaining fields may be missing when running in clusters that have
   105    // members at below CockroachDB v2.0.
   106    optional util.hlc.Timestamp max_timestamp = 3;
   107    repeated ObservedTimestamp observed_timestamps = 4 [(gogoproto.nullable) = false];
   108  }
   109  
   110  // TransactionAbortedReason specifies what caused a TransactionAbortedError.
   111  // The reasons below are not necessarily disjoint - they describe where the
   112  // error was generated, but generally it's possible that a
   113  // TransactionAbortedError would have been generated somewhere else if the
   114  // client would have performed different operations.
   115  enum TransactionAbortedReason {
   116    option (gogoproto.goproto_enum_prefix) = false;
   117  
   118    // For backwards compatibility.
   119    ABORT_REASON_UNKNOWN = 0;
   120  
   121    // A HeartbeatTxn or EndTxn(commit=true) request found an aborted transaction
   122    // record. Another txn must have written this record - that other txn probably
   123    // ran into one of our intents and pushed our transaction record successfully.
   124    // Either a high-priority transaction simply pushed us or we failed to
   125    // heartbeat for a while and another txn (of any priority) considered us
   126    // abandoned and pushed us.
   127    ABORT_REASON_ABORTED_RECORD_FOUND = 1;
   128  
   129    // The client is trying to use a transaction that's already been aborted. The
   130    // TxnCoordSender detects this. Either the client is misusing a txn, or the
   131    // TxnCoordSender found out about the transaction being aborted async through
   132    // the heartbeat loop.
   133    ABORT_REASON_CLIENT_REJECT = 3;
   134  
   135    // The txn was trying to push another and found out that it itself got aborted
   136    // somehow while waiting for the push.
   137    ABORT_REASON_PUSHER_ABORTED = 4;
   138  
   139    // The txn ran into the "abort span" - it was trying to read from a range
   140    // where it had previously laid down intents that have been cleaned up in the
   141    // meantime because the transaction was aborted.
   142    ABORT_REASON_ABORT_SPAN = 5;
   143  
   144    // A request attempting to create a transaction record encountered a write
   145    // timestamp cache entry for the txn key, and the entry identifies this
   146    // transaction. This means that the transaction definitely committed or rolled
   147    // back before. So, this request is either a delayed replay of some sort, or
   148    // it raced with an async abort and lost. If a client gets this
   149    // TransactionAbortedError (without it being wrapped in an ambiguous error),
   150    // it must be the latter case, and the transaction can be retried.
   151    ABORT_REASON_ALREADY_COMMITTED_OR_ROLLED_BACK_POSSIBLE_REPLAY = 6;
   152  
   153    // A request attempting to create a transaction record is not allowed to
   154    // proceed by the timestamp cache because it cannot be verified that the
   155    // respective transaction record did not previously exist. As opposed to the
   156    // case above, the timestamp cache does not have a txn id in it, but the lease
   157    // under which the request is evaluated is newer than the transaction's
   158    // minimum timestamp (see CanCreateTxnRecord()). A new lease wipes the
   159    // timestamp cache, so transaction record creation is bound to fail for
   160    // transactions that spanned a lease acquisition.
   161    // As above, if the error has not been converted by the time it reaches a
   162    // client, then it's not a replay.
   163    ABORT_REASON_NEW_LEASE_PREVENTS_TXN = 8;
   164  
   165    // Like the above, the timestamp cache rejects the creation of a transaction
   166    // record. But there's no txn id in the ts cache, and also the lease is not
   167    // new. The timestamp cache has lost accuracy because of a range merge or
   168    // because of its memory limit.
   169    // As above, if the error has not been converted by the time it reaches a
   170    // client, then it's not a replay.
   171    //
   172    // TODO(andrei): We should be able to identify the range merge case by saving
   173    // a bit more info in the timestamp cache.
   174    ABORT_REASON_TIMESTAMP_CACHE_REJECTED = 7;
   175    
   176    reserved 2;
   177  }
   178  
   179  // A TransactionAbortedError indicates that the client should retry the
   180  // transaction (and use a different txn id, as opposed to
   181  // TransactionRetryError). This most often happens when the transaction was
   182  // aborted by another concurrent transaction. Upon seeing this error, the client
   183  // is supposed to reset its Transaction proto and try the transaction again.
   184  //
   185  // In contrast with other errors, the Transaction that the client gets in the
   186  // pErr carrying this ErrorDetail is not supposed to be used as is by the
   187  // client; the ID should be checked and then attributes like the timestamp
   188  // should be used in creating a new txn.
   189  message TransactionAbortedError {
   190    option (gogoproto.equal) = true;
   191  
   192    optional TransactionAbortedReason reason = 1 [(gogoproto.nullable) = false];
   193  }
   194  
   195  // A TransactionPushError indicates that the transaction could not
   196  // continue because it encountered a write intent from another
   197  // transaction which it was unable to push.
   198  message TransactionPushError {
   199    option (gogoproto.equal) = true;
   200  
   201    optional Transaction pushee_txn = 1 [(gogoproto.nullable) = false];
   202  }
   203  
   204  // TransactionRetryReason specifies what caused a transaction retry.
   205  enum TransactionRetryReason {
   206    option (gogoproto.goproto_enum_prefix) = false;
   207  
   208    // For backwards compatibility.
   209    RETRY_REASON_UNKNOWN = 0;
   210    // A concurrent writer finished first, causing restart.
   211    RETRY_WRITE_TOO_OLD = 1;
   212    // A SERIALIZABLE transaction had its timestamp moved forward.
   213    RETRY_SERIALIZABLE = 3;
   214    // An asynchronous write was observed to have failed.
   215    RETRY_ASYNC_WRITE_FAILURE = 5;
   216    // The transaction exceeded its deadline.
   217    RETRY_COMMIT_DEADLINE_EXCEEDED = 6;
   218  }
   219  
   220  // A TransactionRetryError indicates that the transaction must be
   221  // retried, usually with an increased transaction timestamp.
   222  message TransactionRetryError {
   223    option (gogoproto.equal) = true;
   224  
   225    optional TransactionRetryReason reason = 1 [(gogoproto.nullable) = false];
   226    optional string extra_msg = 2 [(gogoproto.nullable) = false];
   227  }
   228  
   229  // A TransactionStatusError indicates that the transaction status is
   230  // incompatible with the requested operation. This might mean the
   231  // transaction has already been committed. It might also be the case
   232  // that the request to modify the transaction failed due to a
   233  // regression in transaction epoch or timestamp, both of which may
   234  // only monotonically increase.
   235  message TransactionStatusError {
   236    option (gogoproto.equal) = true;
   237  
   238    optional string msg = 1 [(gogoproto.nullable) = false];
   239  
   240    // Reason specifies what caused the error.
   241    enum Reason {
   242      // For backwards compatibility.
   243      REASON_UNKNOWN = 0;
   244      // A committed transaction record was found.
   245      REASON_TXN_COMMITTED = 2;
   246  
   247      reserved 1;
   248    }
   249    optional Reason reason = 2 [(gogoproto.nullable) = false];
   250  }
   251  
   252  // A WriteIntentError indicates that one or more write intent
   253  // belonging to another transaction were encountered leading to a
   254  // read/write or write/write conflict. The keys at which the intent
   255  // was encountered are set, as are the txn records for the intents'
   256  // transactions.
   257  message WriteIntentError {
   258    option (gogoproto.equal) = true;
   259  
   260    repeated Intent intents = 1 [(gogoproto.nullable) = false];
   261    reserved 2;
   262  }
   263  
   264  // A WriteTooOldError indicates that a write encountered a versioned
   265  // value newer than its timestamp, making it impossible to rewrite
   266  // history. The write is instead done at actual timestamp, which is
   267  // the timestamp of the existing version+1.
   268  message WriteTooOldError {
   269    option (gogoproto.equal) = true;
   270  
   271    optional util.hlc.Timestamp timestamp = 1 [(gogoproto.nullable) = false];
   272    optional util.hlc.Timestamp actual_timestamp = 2 [(gogoproto.nullable) = false];
   273  }
   274  
   275  // An OpRequiresTxnError indicates that a command required to be
   276  // carried out in a transactional context but was not.
   277  // For example, a Scan which spans ranges requires a transaction.
   278  // The operation should be retried inside of a transaction.
   279  message OpRequiresTxnError {
   280    option (gogoproto.equal) = true;
   281  }
   282  
   283  // A ConditionFailedError indicates that the expected value
   284  // of a ConditionalPutRequest was not found, either
   285  // because it was missing or was not equal. The error will
   286  // contain the actual value found.
   287  message ConditionFailedError {
   288    option (gogoproto.equal) = true;
   289  
   290    optional Value actual_value = 1;
   291  }
   292  
   293  // A LeaseRejectedError indicates that the requested replica could
   294  // not acquire the desired lease because of an existing range lease.
   295  message LeaseRejectedError {
   296    option (gogoproto.equal) = true;
   297  
   298    optional string message = 1 [(gogoproto.nullable) = false];
   299    optional Lease requested = 2 [(gogoproto.nullable) = false];
   300    optional Lease existing = 3 [(gogoproto.nullable) = false];
   301  }
   302  
   303  // A SendError indicates that there was a problem communicating with a replica
   304  // that can evaluate the request. It's possible that the request was, in fact,
   305  // evaluated by a replica successfully but then the server connection dropped.
   306  //
   307  // This error is produced by the DistSender. Note that the DistSender generates
   308  // AmbiguousResultError instead of SendError when there's an EndTxn(commit) in
   309  // the BatchRequest. But also note that the sever can return
   310  // AmbiguousResultErrors too, in which case the DistSender will pipe it through.
   311  // TODO(andrei): clean up this stuff and tighten the meaning of the different
   312  // errors.
   313  message SendError {
   314    option (gogoproto.equal) = true;
   315  
   316    optional string message = 1 [(gogoproto.nullable) = false];
   317    reserved 2;
   318  }
   319  
   320  // An AmbiguousResultError indicates that a request may have succeeded or
   321  // failed, but the response was not received and the final result is ambiguous.
   322  //
   323  // Also see SendError.
   324  message AmbiguousResultError {
   325    option (gogoproto.equal) = true;
   326  
   327    optional string message = 1 [(gogoproto.nullable) = false];
   328    // This can be set to give extra information about which error was converted
   329    // into an AmbiguousResultError. Useful for tests.
   330    optional Error wrapped_err = 2;
   331  }
   332  
   333  // A RaftGroupDeletedError indicates a raft group has been deleted for
   334  // the replica.
   335  message RaftGroupDeletedError {
   336    option (gogoproto.equal) = true;
   337  }
   338  
   339  // A ReplicaCorruptionError indicates that the replica has experienced
   340  // an error which puts its integrity at risk.
   341  message ReplicaCorruptionError {
   342    option (gogoproto.equal) = true;
   343  
   344    optional string error_msg = 1 [(gogoproto.nullable) = false];
   345    // processed indicates that the error has been taken into account and
   346    // necessary steps will be taken. For now, required for testing.
   347    optional bool processed = 2 [(gogoproto.nullable) = false];
   348  }
   349  
   350  // ReplicaTooOldError is sent in response to a raft message when the
   351  // recipient of the raft message believes the sender of the raft
   352  // message to have been removed from the raft group
   353  message ReplicaTooOldError {
   354    option (gogoproto.equal) = true;
   355  
   356    // replica_id is the ID of the replica that is too old.
   357    optional int32 replica_id = 1 [(gogoproto.nullable) = false,
   358        (gogoproto.customname) = "ReplicaID", (gogoproto.casttype) = "ReplicaID"];
   359  }
   360  
   361  // A StoreNotFoundError indicates that a command was sent to a store
   362  // which is not hosted on this node.
   363  message StoreNotFoundError {
   364    option (gogoproto.equal) = true;
   365  
   366    optional int64 store_id = 1 [(gogoproto.nullable) = false,
   367        (gogoproto.customname) = "StoreID", (gogoproto.casttype) = "StoreID"];
   368  }
   369  
   370  // UnhandledRetryableError tells the recipient that a KV request must be
   371  // retried. In case the request was transactional, the whole transaction needs
   372  // to be retried. This is returned generally as a result of a transaction
   373  // conflict.
   374  //
   375  // This error is generated by pErr.GoError() in case of a retryable
   376  // error (other than TransactionRetryWithProtoRefreshError). For transactional
   377  // requests, the TxnCoordSender handles retryable pErrs and transforms
   378  // them into TransactionRetryWithProtoRefreshError. For non-transactional requests,
   379  // this error will be observed by layers above the TxnCoordSender.
   380  message UnhandledRetryableError {
   381    // The underlying storage error that is being marshaled.
   382    // pErr.TransactionRestart is expected to be set, and the error
   383    // detail is one of the retryable ones.
   384    optional Error pErr = 1 [(gogoproto.nullable) = false];
   385  }
   386  
   387  // TransactionRetryWithProtoRefreshError is an error detail representing a retryable error
   388  // that has been "handled" by the TxnCoordSender. This error is produced by the
   389  // TxnCoordSender and is only produced for transactional requests.
   390  //
   391  // It contains the final form of the Transaction proto that should be used on
   392  // next attempts. After being produced by the TxnCoordSender, this error is
   393  // handled first by the client.Txn, which uses the Transaction inside to update
   394  // its state, and then passed along to SQL in a pErr (through the
   395  // client.Sender() interface).
   396  message TransactionRetryWithProtoRefreshError {
   397    option (gogoproto.equal) = true;
   398  
   399    // A user-readable message.
   400    optional string msg = 1 [(gogoproto.nullable) = false];
   401  
   402    // The ID of the transaction being restarted. The client is supposed to check
   403    // this against the ID of its transaction and make sure the retryable error
   404    // is meant for its level and didn't escape from some inner transaction.
   405    optional bytes txn_id = 2 [
   406      (gogoproto.customtype) = "github.com/cockroachdb/cockroach/pkg/util/uuid.UUID",
   407      (gogoproto.customname) = "TxnID",
   408      (gogoproto.nullable) = false];
   409  
   410    // The Transaction that should be used by next attempts. Depending on the
   411    // original cause of this method, this can either be the same Transaction as
   412    // before, but with an incremented epoch and timestamp, or a completely new
   413    // Transaction.
   414    optional Transaction transaction = 3 [(gogoproto.nullable) = false];
   415  }
   416  
   417  // TxnAlreadyEncounteredErrorError indicates that an operation tried to use a
   418  // transaction that already received an error from a previous request. Once that
   419  // happens, client.Txn rejects future requests.
   420  message TxnAlreadyEncounteredErrorError{
   421    option (gogoproto.equal) = true;
   422  
   423    // prev_error is the message from the error that the txn encountered
   424    // previously.
   425    optional string prev_error = 1 [(gogoproto.nullable) = false];
   426  }
   427  
   428  // An IntegerOverflowError indicates that an operation was aborted because
   429  // it would have caused an integeter overflow.
   430  message IntegerOverflowError {
   431    option (gogoproto.equal) = true;
   432  
   433    optional bytes key = 1 [(gogoproto.casttype) = "Key"];
   434    optional int64 current_value = 2 [(gogoproto.nullable) = false];
   435    optional int64 increment_value = 3 [(gogoproto.nullable) = false];
   436  }
   437  
   438  // A BatchTimestampBeforeGCError indicates that a request's timestamp was
   439  // before the GC threshold.
   440  message BatchTimestampBeforeGCError {
   441    option (gogoproto.equal) = true;
   442  
   443    optional util.hlc.Timestamp Timestamp = 1 [(gogoproto.nullable) = false];
   444    optional util.hlc.Timestamp Threshold = 2 [(gogoproto.nullable) = false];
   445  }
   446  
   447  // An IntentMissingError indicates that a QueryIntent request expected
   448  // an intent to be present at its specified key but the intent was
   449  // not there.
   450  message IntentMissingError {
   451    option (gogoproto.equal) = true;
   452  
   453    // The non-matching intent that was found at that key, if any.
   454    optional Intent wrong_intent = 1;
   455    // The key where the intent was expected.
   456    optional bytes key = 2 [(gogoproto.casttype) = "Key"];
   457  }
   458  
   459  // A MergeInProgressError indicates that the request could not be completed
   460  // because the replica is being merged into its left-hand neighbor. The request
   461  // should be resubmitted after the merge completes.
   462  //
   463  // This error is handled by the Store and should not escape to higher levels.
   464  message MergeInProgressError {
   465    option (gogoproto.equal) = true;
   466  }
   467  
   468  // A RangeFeedRetryError indicates that a rangefeed was disconnected, often
   469  // because of a range lifecycle event, and can be retried.
   470  message RangeFeedRetryError {
   471    option (gogoproto.equal) = true;
   472  
   473    // Reason specifies what caused the error.
   474    enum Reason {
   475      // The replica was removed from its store.
   476      REASON_REPLICA_REMOVED = 0;
   477      // The range was split in two.
   478      REASON_RANGE_SPLIT = 1;
   479      // The range was merged into another.
   480      REASON_RANGE_MERGED = 2;
   481      // A Raft snapshot applied on the replica.
   482      REASON_RAFT_SNAPSHOT = 3;
   483      // A Raft command was missing a logical operation log.
   484      REASON_LOGICAL_OPS_MISSING = 4;
   485      // The consumer was processing events too slowly to keep up with live raft
   486      // events.
   487      REASON_SLOW_CONSUMER = 5;
   488    }
   489    optional Reason reason = 1 [(gogoproto.nullable) = false];
   490  }
   491  
   492  // A IndeterminateCommitError indicates that a transaction was encountered with
   493  // a STAGING status. In this state, it is unclear by observing the transaction
   494  // record alone whether the transaction should be committed or aborted. To make
   495  // this determination, the transaction recovery process must be initiated. This
   496  // process makes a ruling on the final state of the transaction based on the
   497  // outcome of its in-flight writes at the time of staging.
   498  message IndeterminateCommitError {
   499    option (gogoproto.equal) = true;
   500  
   501    optional Transaction staging_txn = 1 [(gogoproto.nullable) = false];
   502  }
   503  
   504  // ErrorDetail is a union type containing all available errors.
   505  message ErrorDetail {
   506    option (gogoproto.equal) = true;
   507  
   508    reserved 22, 25, 29, 30, 33;
   509    oneof value {
   510      NotLeaseHolderError not_lease_holder = 1;
   511      RangeNotFoundError range_not_found = 2;
   512      RangeKeyMismatchError range_key_mismatch = 3;
   513      ReadWithinUncertaintyIntervalError read_within_uncertainty_interval = 4;
   514      TransactionAbortedError transaction_aborted = 5;
   515      TransactionPushError transaction_push = 6;
   516      TransactionRetryError transaction_retry = 7;
   517      TransactionStatusError transaction_status = 8;
   518      WriteIntentError write_intent = 9;
   519      WriteTooOldError write_too_old = 10;
   520      OpRequiresTxnError op_requires_txn = 11;
   521      ConditionFailedError condition_failed = 12;
   522      LeaseRejectedError lease_rejected = 13;
   523      NodeUnavailableError node_unavailable = 14;
   524      SendError send = 15;
   525      // TODO(kaneda): Following three are added to preserve the type when
   526      // converting Go errors from/to proto Errors. Revisit this design.
   527      RaftGroupDeletedError raft_group_deleted = 16;
   528      ReplicaCorruptionError replica_corruption = 17;
   529      ReplicaTooOldError replica_too_old = 18;
   530      AmbiguousResultError ambiguous_result = 26;
   531      StoreNotFoundError store_not_found = 27;
   532      // The following three are ErrorDetails (and proto messages) because they
   533      // needs to be communicated from the TxnCoordSender and Txn to the upper
   534      // layers through the Sender interface.
   535      TransactionRetryWithProtoRefreshError transaction_retry_with_proto_refresh = 28;
   536      IntegerOverflowError integer_overflow = 31;
   537      UnsupportedRequestError unsupported_request = 32;
   538      BatchTimestampBeforeGCError timestamp_before = 34;
   539      TxnAlreadyEncounteredErrorError txn_already_encountered_error = 35;
   540      IntentMissingError intent_missing = 36;
   541      MergeInProgressError merge_in_progress = 37;
   542      RangeFeedRetryError rangefeed_retry = 38;
   543      IndeterminateCommitError indeterminate_commit = 39;
   544    }
   545  }
   546  
   547  // TransactionRestart indicates how an error should be handled in a
   548  // transactional context.
   549  enum TransactionRestart {
   550    // NONE (the default) is used for errors which have no effect on the
   551    // transaction state. That is, a transactional operation which receives such
   552    // an error is still PENDING and does not need to restart (at least not as a
   553    // result of the error). Examples are a CPut whose condition wasn't met, or
   554    // a spurious RPC error.
   555    NONE = 0;
   556  
   557    // BACKOFF is for errors that can retried by restarting the transaction
   558    // after an exponential backoff.
   559    // Note: Deprecated.
   560    BACKOFF = 1;
   561  
   562    // IMMEDIATE is for errors that can be retried by restarting the
   563    // transaction immediately.
   564    IMMEDIATE = 2;
   565  }
   566  
   567  // ErrPosition describes the position of an error in a Batch. A simple nullable
   568  // primitive field would break compatibility with proto3, where primitive fields
   569  // are no longer allowed to be nullable.
   570  message ErrPosition {
   571    option (gogoproto.equal) = true;
   572  
   573    optional int32 index = 1 [(gogoproto.nullable) = false];
   574  }
   575  
   576  // Error is a generic representation including a string message
   577  // and information about retryability.
   578  message Error {
   579    option (gogoproto.goproto_stringer) = false;
   580    option (gogoproto.equal) = true;
   581  
   582    // message is a human-readable error message.
   583    optional string message = 1 [(gogoproto.nullable) = false];
   584  
   585    // If transaction_restart is not ABORT, the error condition may be handled by
   586    // restarting the transaction.
   587    optional TransactionRestart transaction_restart = 3 [(gogoproto.nullable) = false];
   588  
   589    // An optional updated transaction. This is to be used by the client in case
   590    // of retryable errors.
   591    //
   592    // Not to be accessed directly - use Error.GetTxn().
   593    optional Transaction unexposed_txn = 4;
   594  
   595    // Node at which the error was generated (zero if does not apply).
   596    optional int32 origin_node = 5 [(gogoproto.nullable) = false, (gogoproto.casttype) = "NodeID"];
   597  
   598    // If an ErrorDetail is present, it may contain additional structured data
   599    // about the error.
   600    optional ErrorDetail detail = 6 [(gogoproto.nullable) = false];
   601  
   602    // The index, if given, contains the index of the request (in the batch)
   603    // whose execution caused the error.
   604    optional ErrPosition index = 7;
   605  
   606    // now is the current time at the node sending the response,
   607    // which can be used by the receiver to update its local HLC.
   608    optional util.hlc.Timestamp now = 8 [(gogoproto.nullable) = false];
   609  
   610    reserved 2;
   611  }