error.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.isResumableError = exports.isNetworkTimeoutError = exports.isSDAMUnrecoverableError = exports.isNodeShuttingDownError = exports.isRetryableReadError = exports.isRetryableWriteError = exports.needsRetryableWriteLabel = exports.MongoWriteConcernError = exports.MongoServerSelectionError = exports.MongoSystemError = exports.MongoMissingDependencyError = exports.MongoMissingCredentialsError = exports.MongoCompatibilityError = exports.MongoInvalidArgumentError = exports.MongoParseError = exports.MongoNetworkTimeoutError = exports.MongoNetworkError = exports.isNetworkErrorBeforeHandshake = exports.MongoTopologyClosedError = exports.MongoCursorExhaustedError = exports.MongoServerClosedError = exports.MongoCursorInUseError = exports.MongoUnexpectedServerResponseError = exports.MongoGridFSChunkError = exports.MongoGridFSStreamError = exports.MongoTailableCursorError = exports.MongoChangeStreamError = exports.MongoAzureError = exports.MongoAWSError = exports.MongoKerberosError = exports.MongoExpiredSessionError = exports.MongoTransactionError = exports.MongoNotConnectedError = exports.MongoDecompressionError = exports.MongoBatchReExecutionError = exports.MongoRuntimeError = exports.MongoAPIError = exports.MongoDriverError = exports.MongoServerError = exports.MongoError = exports.MongoErrorLabel = exports.GET_MORE_RESUMABLE_CODES = exports.MONGODB_ERROR_CODES = exports.NODE_IS_RECOVERING_ERROR_MESSAGE = exports.LEGACY_NOT_PRIMARY_OR_SECONDARY_ERROR_MESSAGE = exports.LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE = void 0;
  4. /** @internal */
  5. const kErrorLabels = Symbol('errorLabels');
  6. /**
  7. * @internal
  8. * The legacy error message from the server that indicates the node is not a writable primary
  9. * https://github.com/mongodb/specifications/blob/b07c26dc40d04ac20349f989db531c9845fdd755/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#not-writable-primary-and-node-is-recovering
  10. */
  11. exports.LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE = new RegExp('not master', 'i');
  12. /**
  13. * @internal
  14. * The legacy error message from the server that indicates the node is not a primary or secondary
  15. * https://github.com/mongodb/specifications/blob/b07c26dc40d04ac20349f989db531c9845fdd755/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#not-writable-primary-and-node-is-recovering
  16. */
  17. exports.LEGACY_NOT_PRIMARY_OR_SECONDARY_ERROR_MESSAGE = new RegExp('not master or secondary', 'i');
  18. /**
  19. * @internal
  20. * The error message from the server that indicates the node is recovering
  21. * https://github.com/mongodb/specifications/blob/b07c26dc40d04ac20349f989db531c9845fdd755/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#not-writable-primary-and-node-is-recovering
  22. */
  23. exports.NODE_IS_RECOVERING_ERROR_MESSAGE = new RegExp('node is recovering', 'i');
  24. /** @internal MongoDB Error Codes */
  25. exports.MONGODB_ERROR_CODES = Object.freeze({
  26. HostUnreachable: 6,
  27. HostNotFound: 7,
  28. NetworkTimeout: 89,
  29. ShutdownInProgress: 91,
  30. PrimarySteppedDown: 189,
  31. ExceededTimeLimit: 262,
  32. SocketException: 9001,
  33. NotWritablePrimary: 10107,
  34. InterruptedAtShutdown: 11600,
  35. InterruptedDueToReplStateChange: 11602,
  36. NotPrimaryNoSecondaryOk: 13435,
  37. NotPrimaryOrSecondary: 13436,
  38. StaleShardVersion: 63,
  39. StaleEpoch: 150,
  40. StaleConfig: 13388,
  41. RetryChangeStream: 234,
  42. FailedToSatisfyReadPreference: 133,
  43. CursorNotFound: 43,
  44. LegacyNotPrimary: 10058,
  45. WriteConcernFailed: 64,
  46. NamespaceNotFound: 26,
  47. IllegalOperation: 20,
  48. MaxTimeMSExpired: 50,
  49. UnknownReplWriteConcern: 79,
  50. UnsatisfiableWriteConcern: 100,
  51. Reauthenticate: 391
  52. });
  53. // From spec@https://github.com/mongodb/specifications/blob/f93d78191f3db2898a59013a7ed5650352ef6da8/source/change-streams/change-streams.rst#resumable-error
  54. exports.GET_MORE_RESUMABLE_CODES = new Set([
  55. exports.MONGODB_ERROR_CODES.HostUnreachable,
  56. exports.MONGODB_ERROR_CODES.HostNotFound,
  57. exports.MONGODB_ERROR_CODES.NetworkTimeout,
  58. exports.MONGODB_ERROR_CODES.ShutdownInProgress,
  59. exports.MONGODB_ERROR_CODES.PrimarySteppedDown,
  60. exports.MONGODB_ERROR_CODES.ExceededTimeLimit,
  61. exports.MONGODB_ERROR_CODES.SocketException,
  62. exports.MONGODB_ERROR_CODES.NotWritablePrimary,
  63. exports.MONGODB_ERROR_CODES.InterruptedAtShutdown,
  64. exports.MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
  65. exports.MONGODB_ERROR_CODES.NotPrimaryNoSecondaryOk,
  66. exports.MONGODB_ERROR_CODES.NotPrimaryOrSecondary,
  67. exports.MONGODB_ERROR_CODES.StaleShardVersion,
  68. exports.MONGODB_ERROR_CODES.StaleEpoch,
  69. exports.MONGODB_ERROR_CODES.StaleConfig,
  70. exports.MONGODB_ERROR_CODES.RetryChangeStream,
  71. exports.MONGODB_ERROR_CODES.FailedToSatisfyReadPreference,
  72. exports.MONGODB_ERROR_CODES.CursorNotFound
  73. ]);
  74. /** @public */
  75. exports.MongoErrorLabel = Object.freeze({
  76. RetryableWriteError: 'RetryableWriteError',
  77. TransientTransactionError: 'TransientTransactionError',
  78. UnknownTransactionCommitResult: 'UnknownTransactionCommitResult',
  79. ResumableChangeStreamError: 'ResumableChangeStreamError',
  80. HandshakeError: 'HandshakeError',
  81. ResetPool: 'ResetPool',
  82. InterruptInUseConnections: 'InterruptInUseConnections',
  83. NoWritesPerformed: 'NoWritesPerformed'
  84. });
  85. function isAggregateError(e) {
  86. return 'errors' in e && Array.isArray(e.errors);
  87. }
  88. /**
  89. * @public
  90. * @category Error
  91. *
  92. * @privateRemarks
  93. * mongodb-client-encryption has a dependency on this error, it uses the constructor with a string argument
  94. */
  95. class MongoError extends Error {
  96. constructor(message) {
  97. super(MongoError.buildErrorMessage(message));
  98. if (message instanceof Error) {
  99. this.cause = message;
  100. }
  101. this[kErrorLabels] = new Set();
  102. }
  103. /** @internal */
  104. static buildErrorMessage(e) {
  105. if (typeof e === 'string') {
  106. return e;
  107. }
  108. if (isAggregateError(e) && e.message.length === 0) {
  109. return e.errors.length === 0
  110. ? 'AggregateError has an empty errors array. Please check the `cause` property for more information.'
  111. : e.errors.map(({ message }) => message).join(', ');
  112. }
  113. return e.message;
  114. }
  115. get name() {
  116. return 'MongoError';
  117. }
  118. /** Legacy name for server error responses */
  119. get errmsg() {
  120. return this.message;
  121. }
  122. /**
  123. * Checks the error to see if it has an error label
  124. *
  125. * @param label - The error label to check for
  126. * @returns returns true if the error has the provided error label
  127. */
  128. hasErrorLabel(label) {
  129. return this[kErrorLabels].has(label);
  130. }
  131. addErrorLabel(label) {
  132. this[kErrorLabels].add(label);
  133. }
  134. get errorLabels() {
  135. return Array.from(this[kErrorLabels]);
  136. }
  137. }
  138. exports.MongoError = MongoError;
  139. /**
  140. * An error coming from the mongo server
  141. *
  142. * @public
  143. * @category Error
  144. */
  145. class MongoServerError extends MongoError {
  146. constructor(message) {
  147. super(message.message || message.errmsg || message.$err || 'n/a');
  148. if (message.errorLabels) {
  149. this[kErrorLabels] = new Set(message.errorLabels);
  150. }
  151. for (const name in message) {
  152. if (name !== 'errorLabels' && name !== 'errmsg' && name !== 'message')
  153. this[name] = message[name];
  154. }
  155. }
  156. get name() {
  157. return 'MongoServerError';
  158. }
  159. }
  160. exports.MongoServerError = MongoServerError;
  161. /**
  162. * An error generated by the driver
  163. *
  164. * @public
  165. * @category Error
  166. */
  167. class MongoDriverError extends MongoError {
  168. constructor(message) {
  169. super(message);
  170. }
  171. get name() {
  172. return 'MongoDriverError';
  173. }
  174. }
  175. exports.MongoDriverError = MongoDriverError;
  176. /**
  177. * An error generated when the driver API is used incorrectly
  178. *
  179. * @privateRemarks
  180. * Should **never** be directly instantiated
  181. *
  182. * @public
  183. * @category Error
  184. */
  185. class MongoAPIError extends MongoDriverError {
  186. constructor(message) {
  187. super(message);
  188. }
  189. get name() {
  190. return 'MongoAPIError';
  191. }
  192. }
  193. exports.MongoAPIError = MongoAPIError;
  194. /**
  195. * An error generated when the driver encounters unexpected input
  196. * or reaches an unexpected/invalid internal state
  197. *
  198. * @privateRemarks
  199. * Should **never** be directly instantiated.
  200. *
  201. * @public
  202. * @category Error
  203. */
  204. class MongoRuntimeError extends MongoDriverError {
  205. constructor(message) {
  206. super(message);
  207. }
  208. get name() {
  209. return 'MongoRuntimeError';
  210. }
  211. }
  212. exports.MongoRuntimeError = MongoRuntimeError;
  213. /**
  214. * An error generated when a batch command is re-executed after one of the commands in the batch
  215. * has failed
  216. *
  217. * @public
  218. * @category Error
  219. */
  220. class MongoBatchReExecutionError extends MongoAPIError {
  221. constructor(message = 'This batch has already been executed, create new batch to execute') {
  222. super(message);
  223. }
  224. get name() {
  225. return 'MongoBatchReExecutionError';
  226. }
  227. }
  228. exports.MongoBatchReExecutionError = MongoBatchReExecutionError;
  229. /**
  230. * An error generated when the driver fails to decompress
  231. * data received from the server.
  232. *
  233. * @public
  234. * @category Error
  235. */
  236. class MongoDecompressionError extends MongoRuntimeError {
  237. constructor(message) {
  238. super(message);
  239. }
  240. get name() {
  241. return 'MongoDecompressionError';
  242. }
  243. }
  244. exports.MongoDecompressionError = MongoDecompressionError;
  245. /**
  246. * An error thrown when the user attempts to operate on a database or collection through a MongoClient
  247. * that has not yet successfully called the "connect" method
  248. *
  249. * @public
  250. * @category Error
  251. */
  252. class MongoNotConnectedError extends MongoAPIError {
  253. constructor(message) {
  254. super(message);
  255. }
  256. get name() {
  257. return 'MongoNotConnectedError';
  258. }
  259. }
  260. exports.MongoNotConnectedError = MongoNotConnectedError;
  261. /**
  262. * An error generated when the user makes a mistake in the usage of transactions.
  263. * (e.g. attempting to commit a transaction with a readPreference other than primary)
  264. *
  265. * @public
  266. * @category Error
  267. */
  268. class MongoTransactionError extends MongoAPIError {
  269. constructor(message) {
  270. super(message);
  271. }
  272. get name() {
  273. return 'MongoTransactionError';
  274. }
  275. }
  276. exports.MongoTransactionError = MongoTransactionError;
  277. /**
  278. * An error generated when the user attempts to operate
  279. * on a session that has expired or has been closed.
  280. *
  281. * @public
  282. * @category Error
  283. */
  284. class MongoExpiredSessionError extends MongoAPIError {
  285. constructor(message = 'Cannot use a session that has ended') {
  286. super(message);
  287. }
  288. get name() {
  289. return 'MongoExpiredSessionError';
  290. }
  291. }
  292. exports.MongoExpiredSessionError = MongoExpiredSessionError;
  293. /**
  294. * A error generated when the user attempts to authenticate
  295. * via Kerberos, but fails to connect to the Kerberos client.
  296. *
  297. * @public
  298. * @category Error
  299. */
  300. class MongoKerberosError extends MongoRuntimeError {
  301. constructor(message) {
  302. super(message);
  303. }
  304. get name() {
  305. return 'MongoKerberosError';
  306. }
  307. }
  308. exports.MongoKerberosError = MongoKerberosError;
  309. /**
  310. * A error generated when the user attempts to authenticate
  311. * via AWS, but fails
  312. *
  313. * @public
  314. * @category Error
  315. */
  316. class MongoAWSError extends MongoRuntimeError {
  317. constructor(message) {
  318. super(message);
  319. }
  320. get name() {
  321. return 'MongoAWSError';
  322. }
  323. }
  324. exports.MongoAWSError = MongoAWSError;
  325. /**
  326. * A error generated when the user attempts to authenticate
  327. * via Azure, but fails.
  328. *
  329. * @public
  330. * @category Error
  331. */
  332. class MongoAzureError extends MongoRuntimeError {
  333. constructor(message) {
  334. super(message);
  335. }
  336. get name() {
  337. return 'MongoAzureError';
  338. }
  339. }
  340. exports.MongoAzureError = MongoAzureError;
  341. /**
  342. * An error generated when a ChangeStream operation fails to execute.
  343. *
  344. * @public
  345. * @category Error
  346. */
  347. class MongoChangeStreamError extends MongoRuntimeError {
  348. constructor(message) {
  349. super(message);
  350. }
  351. get name() {
  352. return 'MongoChangeStreamError';
  353. }
  354. }
  355. exports.MongoChangeStreamError = MongoChangeStreamError;
  356. /**
  357. * An error thrown when the user calls a function or method not supported on a tailable cursor
  358. *
  359. * @public
  360. * @category Error
  361. */
  362. class MongoTailableCursorError extends MongoAPIError {
  363. constructor(message = 'Tailable cursor does not support this operation') {
  364. super(message);
  365. }
  366. get name() {
  367. return 'MongoTailableCursorError';
  368. }
  369. }
  370. exports.MongoTailableCursorError = MongoTailableCursorError;
  371. /** An error generated when a GridFSStream operation fails to execute.
  372. *
  373. * @public
  374. * @category Error
  375. */
  376. class MongoGridFSStreamError extends MongoRuntimeError {
  377. constructor(message) {
  378. super(message);
  379. }
  380. get name() {
  381. return 'MongoGridFSStreamError';
  382. }
  383. }
  384. exports.MongoGridFSStreamError = MongoGridFSStreamError;
  385. /**
  386. * An error generated when a malformed or invalid chunk is
  387. * encountered when reading from a GridFSStream.
  388. *
  389. * @public
  390. * @category Error
  391. */
  392. class MongoGridFSChunkError extends MongoRuntimeError {
  393. constructor(message) {
  394. super(message);
  395. }
  396. get name() {
  397. return 'MongoGridFSChunkError';
  398. }
  399. }
  400. exports.MongoGridFSChunkError = MongoGridFSChunkError;
  401. /**
  402. * An error generated when a **parsable** unexpected response comes from the server.
  403. * This is generally an error where the driver in a state expecting a certain behavior to occur in
  404. * the next message from MongoDB but it receives something else.
  405. * This error **does not** represent an issue with wire message formatting.
  406. *
  407. * #### Example
  408. * When an operation fails, it is the driver's job to retry it. It must perform serverSelection
  409. * again to make sure that it attempts the operation against a server in a good state. If server
  410. * selection returns a server that does not support retryable operations, this error is used.
  411. * This scenario is unlikely as retryable support would also have been determined on the first attempt
  412. * but it is possible the state change could report a selectable server that does not support retries.
  413. *
  414. * @public
  415. * @category Error
  416. */
  417. class MongoUnexpectedServerResponseError extends MongoRuntimeError {
  418. constructor(message) {
  419. super(message);
  420. }
  421. get name() {
  422. return 'MongoUnexpectedServerResponseError';
  423. }
  424. }
  425. exports.MongoUnexpectedServerResponseError = MongoUnexpectedServerResponseError;
  426. /**
  427. * An error thrown when the user attempts to add options to a cursor that has already been
  428. * initialized
  429. *
  430. * @public
  431. * @category Error
  432. */
  433. class MongoCursorInUseError extends MongoAPIError {
  434. constructor(message = 'Cursor is already initialized') {
  435. super(message);
  436. }
  437. get name() {
  438. return 'MongoCursorInUseError';
  439. }
  440. }
  441. exports.MongoCursorInUseError = MongoCursorInUseError;
  442. /**
  443. * An error generated when an attempt is made to operate
  444. * on a closed/closing server.
  445. *
  446. * @public
  447. * @category Error
  448. */
  449. class MongoServerClosedError extends MongoAPIError {
  450. constructor(message = 'Server is closed') {
  451. super(message);
  452. }
  453. get name() {
  454. return 'MongoServerClosedError';
  455. }
  456. }
  457. exports.MongoServerClosedError = MongoServerClosedError;
  458. /**
  459. * An error thrown when an attempt is made to read from a cursor that has been exhausted
  460. *
  461. * @public
  462. * @category Error
  463. */
  464. class MongoCursorExhaustedError extends MongoAPIError {
  465. constructor(message) {
  466. super(message || 'Cursor is exhausted');
  467. }
  468. get name() {
  469. return 'MongoCursorExhaustedError';
  470. }
  471. }
  472. exports.MongoCursorExhaustedError = MongoCursorExhaustedError;
  473. /**
  474. * An error generated when an attempt is made to operate on a
  475. * dropped, or otherwise unavailable, database.
  476. *
  477. * @public
  478. * @category Error
  479. */
  480. class MongoTopologyClosedError extends MongoAPIError {
  481. constructor(message = 'Topology is closed') {
  482. super(message);
  483. }
  484. get name() {
  485. return 'MongoTopologyClosedError';
  486. }
  487. }
  488. exports.MongoTopologyClosedError = MongoTopologyClosedError;
  489. /** @internal */
  490. const kBeforeHandshake = Symbol('beforeHandshake');
  491. function isNetworkErrorBeforeHandshake(err) {
  492. return err[kBeforeHandshake] === true;
  493. }
  494. exports.isNetworkErrorBeforeHandshake = isNetworkErrorBeforeHandshake;
  495. /**
  496. * An error indicating an issue with the network, including TCP errors and timeouts.
  497. * @public
  498. * @category Error
  499. */
  500. class MongoNetworkError extends MongoError {
  501. constructor(message, options) {
  502. super(message);
  503. if (options && typeof options.beforeHandshake === 'boolean') {
  504. this[kBeforeHandshake] = options.beforeHandshake;
  505. }
  506. }
  507. get name() {
  508. return 'MongoNetworkError';
  509. }
  510. }
  511. exports.MongoNetworkError = MongoNetworkError;
  512. /**
  513. * An error indicating a network timeout occurred
  514. * @public
  515. * @category Error
  516. *
  517. * @privateRemarks
  518. * mongodb-client-encryption has a dependency on this error with an instanceof check
  519. */
  520. class MongoNetworkTimeoutError extends MongoNetworkError {
  521. constructor(message, options) {
  522. super(message, options);
  523. }
  524. get name() {
  525. return 'MongoNetworkTimeoutError';
  526. }
  527. }
  528. exports.MongoNetworkTimeoutError = MongoNetworkTimeoutError;
  529. /**
  530. * An error used when attempting to parse a value (like a connection string)
  531. * @public
  532. * @category Error
  533. */
  534. class MongoParseError extends MongoDriverError {
  535. constructor(message) {
  536. super(message);
  537. }
  538. get name() {
  539. return 'MongoParseError';
  540. }
  541. }
  542. exports.MongoParseError = MongoParseError;
  543. /**
  544. * An error generated when the user supplies malformed or unexpected arguments
  545. * or when a required argument or field is not provided.
  546. *
  547. *
  548. * @public
  549. * @category Error
  550. */
  551. class MongoInvalidArgumentError extends MongoAPIError {
  552. constructor(message) {
  553. super(message);
  554. }
  555. get name() {
  556. return 'MongoInvalidArgumentError';
  557. }
  558. }
  559. exports.MongoInvalidArgumentError = MongoInvalidArgumentError;
  560. /**
  561. * An error generated when a feature that is not enabled or allowed for the current server
  562. * configuration is used
  563. *
  564. *
  565. * @public
  566. * @category Error
  567. */
  568. class MongoCompatibilityError extends MongoAPIError {
  569. constructor(message) {
  570. super(message);
  571. }
  572. get name() {
  573. return 'MongoCompatibilityError';
  574. }
  575. }
  576. exports.MongoCompatibilityError = MongoCompatibilityError;
  577. /**
  578. * An error generated when the user fails to provide authentication credentials before attempting
  579. * to connect to a mongo server instance.
  580. *
  581. *
  582. * @public
  583. * @category Error
  584. */
  585. class MongoMissingCredentialsError extends MongoAPIError {
  586. constructor(message) {
  587. super(message);
  588. }
  589. get name() {
  590. return 'MongoMissingCredentialsError';
  591. }
  592. }
  593. exports.MongoMissingCredentialsError = MongoMissingCredentialsError;
  594. /**
  595. * An error generated when a required module or dependency is not present in the local environment
  596. *
  597. * @public
  598. * @category Error
  599. */
  600. class MongoMissingDependencyError extends MongoAPIError {
  601. constructor(message, { cause } = {}) {
  602. super(message);
  603. if (cause)
  604. this.cause = cause;
  605. }
  606. get name() {
  607. return 'MongoMissingDependencyError';
  608. }
  609. }
  610. exports.MongoMissingDependencyError = MongoMissingDependencyError;
  611. /**
  612. * An error signifying a general system issue
  613. * @public
  614. * @category Error
  615. */
  616. class MongoSystemError extends MongoError {
  617. constructor(message, reason) {
  618. if (reason && reason.error) {
  619. super(reason.error.message || reason.error);
  620. }
  621. else {
  622. super(message);
  623. }
  624. if (reason) {
  625. this.reason = reason;
  626. }
  627. this.code = reason.error?.code;
  628. }
  629. get name() {
  630. return 'MongoSystemError';
  631. }
  632. }
  633. exports.MongoSystemError = MongoSystemError;
  634. /**
  635. * An error signifying a client-side server selection error
  636. * @public
  637. * @category Error
  638. */
  639. class MongoServerSelectionError extends MongoSystemError {
  640. constructor(message, reason) {
  641. super(message, reason);
  642. }
  643. get name() {
  644. return 'MongoServerSelectionError';
  645. }
  646. }
  647. exports.MongoServerSelectionError = MongoServerSelectionError;
  648. function makeWriteConcernResultObject(input) {
  649. const output = Object.assign({}, input);
  650. if (output.ok === 0) {
  651. output.ok = 1;
  652. delete output.errmsg;
  653. delete output.code;
  654. delete output.codeName;
  655. }
  656. return output;
  657. }
  658. /**
  659. * An error thrown when the server reports a writeConcernError
  660. * @public
  661. * @category Error
  662. */
  663. class MongoWriteConcernError extends MongoServerError {
  664. constructor(message, result) {
  665. if (result && Array.isArray(result.errorLabels)) {
  666. message.errorLabels = result.errorLabels;
  667. }
  668. super(message);
  669. this.errInfo = message.errInfo;
  670. if (result != null) {
  671. this.result = makeWriteConcernResultObject(result);
  672. }
  673. }
  674. get name() {
  675. return 'MongoWriteConcernError';
  676. }
  677. }
  678. exports.MongoWriteConcernError = MongoWriteConcernError;
  679. // https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.rst#retryable-error
  680. const RETRYABLE_READ_ERROR_CODES = new Set([
  681. exports.MONGODB_ERROR_CODES.HostUnreachable,
  682. exports.MONGODB_ERROR_CODES.HostNotFound,
  683. exports.MONGODB_ERROR_CODES.NetworkTimeout,
  684. exports.MONGODB_ERROR_CODES.ShutdownInProgress,
  685. exports.MONGODB_ERROR_CODES.PrimarySteppedDown,
  686. exports.MONGODB_ERROR_CODES.SocketException,
  687. exports.MONGODB_ERROR_CODES.NotWritablePrimary,
  688. exports.MONGODB_ERROR_CODES.InterruptedAtShutdown,
  689. exports.MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
  690. exports.MONGODB_ERROR_CODES.NotPrimaryNoSecondaryOk,
  691. exports.MONGODB_ERROR_CODES.NotPrimaryOrSecondary
  692. ]);
  693. // see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms
  694. const RETRYABLE_WRITE_ERROR_CODES = new Set([
  695. ...RETRYABLE_READ_ERROR_CODES,
  696. exports.MONGODB_ERROR_CODES.ExceededTimeLimit
  697. ]);
  698. function needsRetryableWriteLabel(error, maxWireVersion) {
  699. // pre-4.4 server, then the driver adds an error label for every valid case
  700. // execute operation will only inspect the label, code/message logic is handled here
  701. if (error instanceof MongoNetworkError) {
  702. return true;
  703. }
  704. if (error instanceof MongoError) {
  705. if ((maxWireVersion >= 9 || error.hasErrorLabel(exports.MongoErrorLabel.RetryableWriteError)) &&
  706. !error.hasErrorLabel(exports.MongoErrorLabel.HandshakeError)) {
  707. // If we already have the error label no need to add it again. 4.4+ servers add the label.
  708. // In the case where we have a handshake error, need to fall down to the logic checking
  709. // the codes.
  710. return false;
  711. }
  712. }
  713. if (error instanceof MongoWriteConcernError) {
  714. return RETRYABLE_WRITE_ERROR_CODES.has(error.result?.code ?? error.code ?? 0);
  715. }
  716. if (error instanceof MongoError && typeof error.code === 'number') {
  717. return RETRYABLE_WRITE_ERROR_CODES.has(error.code);
  718. }
  719. const isNotWritablePrimaryError = exports.LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE.test(error.message);
  720. if (isNotWritablePrimaryError) {
  721. return true;
  722. }
  723. const isNodeIsRecoveringError = exports.NODE_IS_RECOVERING_ERROR_MESSAGE.test(error.message);
  724. if (isNodeIsRecoveringError) {
  725. return true;
  726. }
  727. return false;
  728. }
  729. exports.needsRetryableWriteLabel = needsRetryableWriteLabel;
  730. function isRetryableWriteError(error) {
  731. return error.hasErrorLabel(exports.MongoErrorLabel.RetryableWriteError);
  732. }
  733. exports.isRetryableWriteError = isRetryableWriteError;
  734. /** Determines whether an error is something the driver should attempt to retry */
  735. function isRetryableReadError(error) {
  736. const hasRetryableErrorCode = typeof error.code === 'number' ? RETRYABLE_READ_ERROR_CODES.has(error.code) : false;
  737. if (hasRetryableErrorCode) {
  738. return true;
  739. }
  740. if (error instanceof MongoNetworkError) {
  741. return true;
  742. }
  743. const isNotWritablePrimaryError = exports.LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE.test(error.message);
  744. if (isNotWritablePrimaryError) {
  745. return true;
  746. }
  747. const isNodeIsRecoveringError = exports.NODE_IS_RECOVERING_ERROR_MESSAGE.test(error.message);
  748. if (isNodeIsRecoveringError) {
  749. return true;
  750. }
  751. return false;
  752. }
  753. exports.isRetryableReadError = isRetryableReadError;
  754. const SDAM_RECOVERING_CODES = new Set([
  755. exports.MONGODB_ERROR_CODES.ShutdownInProgress,
  756. exports.MONGODB_ERROR_CODES.PrimarySteppedDown,
  757. exports.MONGODB_ERROR_CODES.InterruptedAtShutdown,
  758. exports.MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
  759. exports.MONGODB_ERROR_CODES.NotPrimaryOrSecondary
  760. ]);
  761. const SDAM_NOT_PRIMARY_CODES = new Set([
  762. exports.MONGODB_ERROR_CODES.NotWritablePrimary,
  763. exports.MONGODB_ERROR_CODES.NotPrimaryNoSecondaryOk,
  764. exports.MONGODB_ERROR_CODES.LegacyNotPrimary
  765. ]);
  766. const SDAM_NODE_SHUTTING_DOWN_ERROR_CODES = new Set([
  767. exports.MONGODB_ERROR_CODES.InterruptedAtShutdown,
  768. exports.MONGODB_ERROR_CODES.ShutdownInProgress
  769. ]);
  770. function isRecoveringError(err) {
  771. if (typeof err.code === 'number') {
  772. // If any error code exists, we ignore the error.message
  773. return SDAM_RECOVERING_CODES.has(err.code);
  774. }
  775. return (exports.LEGACY_NOT_PRIMARY_OR_SECONDARY_ERROR_MESSAGE.test(err.message) ||
  776. exports.NODE_IS_RECOVERING_ERROR_MESSAGE.test(err.message));
  777. }
  778. function isNotWritablePrimaryError(err) {
  779. if (typeof err.code === 'number') {
  780. // If any error code exists, we ignore the error.message
  781. return SDAM_NOT_PRIMARY_CODES.has(err.code);
  782. }
  783. if (isRecoveringError(err)) {
  784. return false;
  785. }
  786. return exports.LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE.test(err.message);
  787. }
  788. function isNodeShuttingDownError(err) {
  789. return !!(typeof err.code === 'number' && SDAM_NODE_SHUTTING_DOWN_ERROR_CODES.has(err.code));
  790. }
  791. exports.isNodeShuttingDownError = isNodeShuttingDownError;
  792. /**
  793. * Determines whether SDAM can recover from a given error. If it cannot
  794. * then the pool will be cleared, and server state will completely reset
  795. * locally.
  796. *
  797. * @see https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#not-master-and-node-is-recovering
  798. */
  799. function isSDAMUnrecoverableError(error) {
  800. // NOTE: null check is here for a strictly pre-CMAP world, a timeout or
  801. // close event are considered unrecoverable
  802. if (error instanceof MongoParseError || error == null) {
  803. return true;
  804. }
  805. return isRecoveringError(error) || isNotWritablePrimaryError(error);
  806. }
  807. exports.isSDAMUnrecoverableError = isSDAMUnrecoverableError;
  808. function isNetworkTimeoutError(err) {
  809. return !!(err instanceof MongoNetworkError && err.message.match(/timed out/));
  810. }
  811. exports.isNetworkTimeoutError = isNetworkTimeoutError;
  812. function isResumableError(error, wireVersion) {
  813. if (error == null || !(error instanceof MongoError)) {
  814. return false;
  815. }
  816. if (error instanceof MongoNetworkError) {
  817. return true;
  818. }
  819. if (wireVersion != null && wireVersion >= 9) {
  820. // DRIVERS-1308: For 4.4 drivers running against 4.4 servers, drivers will add a special case to treat the CursorNotFound error code as resumable
  821. if (error.code === exports.MONGODB_ERROR_CODES.CursorNotFound) {
  822. return true;
  823. }
  824. return error.hasErrorLabel(exports.MongoErrorLabel.ResumableChangeStreamError);
  825. }
  826. if (typeof error.code === 'number') {
  827. return exports.GET_MORE_RESUMABLE_CODES.has(error.code);
  828. }
  829. return false;
  830. }
  831. exports.isResumableError = isResumableError;
  832. //# sourceMappingURL=error.js.map