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 }