fix: preserve originalError on EABORT TransactionError#1850
Open
dhensby wants to merge 1 commit into
Open
Conversation
0af990b to
bc36e09
Compare
There was a problem hiding this comment.
Pull request overview
This PR preserves the underlying abort cause on EABORT transaction errors so consumers can inspect originalError after server-aborted transactions.
Changes:
- Tracks
_abortReasonon transactions and attaches it to generatedEABORTerrors. - Captures request errors in tedious request completion paths and provides a generic abort fallback.
- Adds unit coverage for base transaction abort error behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
lib/base/transaction.js |
Adds abort reason tracking and EABORT error construction. |
lib/tedious/transaction.js |
Sets a generic server-rollback abort reason fallback. |
lib/tedious/request.js |
Attempts to capture request errors as transaction abort reasons. |
test/common/unit.js |
Adds unit tests for EABORT originalError behavior. |
Comments suppressed due to low confidence (2)
lib/tedious/request.js:509
- In streaming mode
erroris never populated because the code only assigns it when!this.stream, so this branch cannot preserve the actual request error for an aborted streaming query. The request errors are still collected inerrorsfor stream mode, so use the last collected error (when present) to set_abortReasonbefore invoking the callback.
if (error && this.parent._aborted) {
this.parent._abortReason = error
}
lib/tedious/request.js:876
- In streaming mode
errorremains undefined because it is assigned only inside the!this.streambranch, so aborted streaming executions keep only the generic fallback instead of the actual request error. Sinceerrorsis populated for stream mode too, set_abortReasonfrom the last collected error when the transaction has been aborted.
if (error && this.parent._aborted) {
this.parent._abortReason = error
}
When a transaction is aborted (e.g. by XACT_ABORT or deadlock), subsequent commit() or rollback() calls return a TransactionError with code EABORT. Previously, originalError was always undefined on these errors because the error was constructed with a string message rather than an Error object. Now the actual request error that triggered the abort is captured and attached as originalError on the EABORT TransactionError. A generic fallback is used when the specific error cannot be captured (e.g. connection-level errors). Closes tediousjs#1716 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
48075c6 to
b9e9826
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a transaction is aborted by the server (e.g. due to
XACT_ABORTor a deadlock), subsequentcommit()orrollback()calls return aTransactionErrorwith codeEABORT. However,originalErrorwas alwaysundefinedon these errors because the error was constructed with a string message rather than anErrorobject.This made it difficult for consumers to understand why the transaction was aborted without correlating errors manually.
Closes #1716
Solution
Capture the actual request error — When a request completes with an error and the transaction has been aborted, the error is stored as
_abortReasonon the transaction. This is done in the tedious request completion handlers (_query,_execute,_bulk).Generic fallback — The tedious
_aborthandler (fired by therollbackTransactionevent) sets a generic"Transaction was rolled back by the server"fallback reason for edge cases where the specific error cannot be captured (e.g. connection-level errors).Attach as
originalError— A new_createAbortError()helper on the baseTransactionclass constructs the EABORTTransactionErrorand attaches_abortReasonasoriginalErrorusingObject.defineProperty(matching the pattern used elsewhere inMSSQLError).Changes
lib/base/transaction.js— Added_abortReasontracking,_createAbortError()helper, reset on_begin()lib/tedious/transaction.js— Generic fallback_abortReasonin_aborthandlerlib/tedious/request.js— Capture actual request error as abort reason in_query,_execute,_bulkcompletion pathstest/common/unit.js— 4 new unit tests for EABORToriginalErrorbehaviorExample