error.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. 'use strict';
  2. const mongoErrorContextSymbol = Symbol('mongoErrorContextSymbol');
  3. /**
  4. * Creates a new MongoError
  5. *
  6. * @augments Error
  7. * @param {Error|string|object} message The error message
  8. * @property {string} message The error message
  9. * @property {string} stack The error call stack
  10. */
  11. class MongoError extends Error {
  12. constructor(message) {
  13. if (message instanceof Error) {
  14. super(message.message);
  15. this.stack = message.stack;
  16. } else {
  17. if (typeof message === 'string') {
  18. super(message);
  19. } else {
  20. super(message.message || message.errmsg || message.$err || 'n/a');
  21. for (var name in message) {
  22. this[name] = message[name];
  23. }
  24. }
  25. Error.captureStackTrace(this, this.constructor);
  26. }
  27. this.name = 'MongoError';
  28. this[mongoErrorContextSymbol] = this[mongoErrorContextSymbol] || {};
  29. }
  30. /**
  31. * Creates a new MongoError object
  32. *
  33. * @param {Error|string|object} options The options used to create the error.
  34. * @return {MongoError} A MongoError instance
  35. * @deprecated Use `new MongoError()` instead.
  36. */
  37. static create(options) {
  38. return new MongoError(options);
  39. }
  40. hasErrorLabel(label) {
  41. return this.errorLabels && this.errorLabels.indexOf(label) !== -1;
  42. }
  43. }
  44. /**
  45. * Creates a new MongoNetworkError
  46. *
  47. * @param {Error|string|object} message The error message
  48. * @property {string} message The error message
  49. * @property {string} stack The error call stack
  50. */
  51. class MongoNetworkError extends MongoError {
  52. constructor(message) {
  53. super(message);
  54. this.name = 'MongoNetworkError';
  55. // This is added as part of the transactions specification
  56. this.errorLabels = ['TransientTransactionError'];
  57. }
  58. }
  59. /**
  60. * An error used when attempting to parse a value (like a connection string)
  61. *
  62. * @param {Error|string|object} message The error message
  63. * @property {string} message The error message
  64. */
  65. class MongoParseError extends MongoError {
  66. constructor(message) {
  67. super(message);
  68. this.name = 'MongoParseError';
  69. }
  70. }
  71. /**
  72. * An error signifying a timeout event
  73. *
  74. * @param {Error|string|object} message The error message
  75. * @property {string} message The error message
  76. */
  77. class MongoTimeoutError extends MongoError {
  78. constructor(message) {
  79. super(message);
  80. this.name = 'MongoTimeoutError';
  81. }
  82. }
  83. function makeWriteConcernResultObject(input) {
  84. const output = Object.assign({}, input);
  85. if (output.ok === 0) {
  86. output.ok = 1;
  87. delete output.errmsg;
  88. delete output.code;
  89. delete output.codeName;
  90. }
  91. return output;
  92. }
  93. /**
  94. * An error thrown when the server reports a writeConcernError
  95. *
  96. * @param {Error|string|object} message The error message
  97. * @param {object} result The result document (provided if ok: 1)
  98. * @property {string} message The error message
  99. * @property {object} [result] The result document (provided if ok: 1)
  100. */
  101. class MongoWriteConcernError extends MongoError {
  102. constructor(message, result) {
  103. super(message);
  104. this.name = 'MongoWriteConcernError';
  105. if (result != null) {
  106. this.result = makeWriteConcernResultObject(result);
  107. }
  108. }
  109. }
  110. // see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms
  111. const RETRYABLE_ERROR_CODES = new Set([
  112. 6, // HostUnreachable
  113. 7, // HostNotFound
  114. 89, // NetworkTimeout
  115. 91, // ShutdownInProgress
  116. 189, // PrimarySteppedDown
  117. 9001, // SocketException
  118. 10107, // NotMaster
  119. 11600, // InterruptedAtShutdown
  120. 11602, // InterruptedDueToReplStateChange
  121. 13435, // NotMasterNoSlaveOk
  122. 13436 // NotMasterOrSecondary
  123. ]);
  124. /**
  125. * Determines whether an error is something the driver should attempt to retry
  126. *
  127. * @param {MongoError|Error} error
  128. */
  129. function isRetryableError(error) {
  130. return (
  131. RETRYABLE_ERROR_CODES.has(error.code) ||
  132. error instanceof MongoNetworkError ||
  133. error.message.match(/not master/) ||
  134. error.message.match(/node is recovering/)
  135. );
  136. }
  137. module.exports = {
  138. MongoError,
  139. MongoNetworkError,
  140. MongoParseError,
  141. MongoTimeoutError,
  142. MongoWriteConcernError,
  143. mongoErrorContextSymbol,
  144. isRetryableError
  145. };