I am currently debugging some tests written with jest over typescript and I'm having a bit of a headache.
If a test, or tested class, runs Postgres SQL and there is an error in the query, I get the wrong stack trace, for example, this:
error: invalid input syntax for type integer: ""0""
at Parser.parseErrorMessage (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:369:69)
at Parser.handlePacket (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:188:21)
at Parser.parse (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:103:30)
at Socket.<anonymous> (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/index.ts:7:48)
at Socket.emit (node:events:365:28)
at addChunk (node:internal/streams/readable:314:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
The "error" line is very useful, however, the stack trace only tells me that the error was thrown by the pg-protocol driver. I would like to know which line within my code generated the error.
I am exactly 82.7% sure that this is due to PG's query
being async.
It is incredibly time-consuming having to step debug or (gasp) console.log
my way to each error when it would only be a matter of showing the correct call stack in order to make it better.
Has anyone found a way of making this developer-friendly?
You can obtain a stack trace from a thread – by calling the getStackTrace method on that Thread instance. This invocation returns an array of StackTraceElement, from which details about stack frames of the thread can be extracted.
Use the console. trace() method to get the stack trace from an error. The console. trace() method outputs the stack trace and shows the call path taken to reach the point at which the method was called.
You can easily see the stack trace in JavaScript by adding the following into your code: console. trace(); And you'll get an outputted stack trace.
Therefore, you should log a stacktrace if, and only if, and always if, the exception indicates a bug in the program. However, that does not always indicate that a method you write should catch and log the exception.
Lists all tests as JSON that Jest will run given the arguments, and exits. This can be used together with --findRelatedTests to know which tests Jest will run. Logs the heap usage after every test.
Attempt to collect and print open handles preventing Jest from exiting cleanly. Use this in cases where you need to use --forceExit in order for Jest to exit to potentially track down the reason. This implies --runInBand, making tests run serially. Implemented using async_hooks.
The jest command line runner has a number of useful options. You can run jest --help to view all available options. Many of the options shown below can also be used together to run tests exactly the way you want. Every one of Jest's Configuration options can also be specified through the CLI. Here is a brief overview: Run all tests (default):
Insert Jest's globals ( expect, test, describe, beforeEach etc.) into the global environment. If you set this to false, you should import from @jest/globals, e.g. Note: This option is only supported using the default jest-circus test runner. Prints the test results in JSON. This mode will send all other test output and user messages to stderr.
Check if this is related to brianc/node-postgres
issue 2484
is (there) a preferred package, extension, or method for providing more detail when you get a syntax error back from the parser?
(for instance, one that listed line number, column of the error)for instance, right now:
error: syntax error at or near "as" at Parser.parseErrorMessage (/home/collspec/projects/staff-portal/sprint-server/node_modules/pg-protocol/dist/parser.js:278:15)
desired behavior:
error: syntax error at or near "as", line 5, column 7 at Parser.parseErrorMessage (/home/collspec/projects/staff-portal/sprint-server/node_modules/pg-protocol/dist/parser.js:278:15)
Possible workaround from that issue:
There are a bunch of additional fields on Error objects populated by the driver.
If you log the error object you can see them. They correspond to the error fields returned by the server:For example with the command:
SELECT foo FROM bar
You can get an error like this:
{ length: 102, severity: 'ERROR', code: '42P01', detail: undefined, hint: undefined, position: '17', internalPosition: undefined, internalQuery: undefined, where: undefined, schema: undefined, table: undefined, column: undefined, dataType: undefined, constraint: undefined, file: 'parse_relation.c', line: '1180', routine: 'parserOpenTable' }
The one you want is position. It gives you the character offset in the SQL of the error.
In this example the position value of "17" refers to the start of the bar token in the SQL.
It's not always populated though as it depends on what caused the error (generally just parse errors).
I ran into a similar issue with aws-sdk for DynamoDb. This is a stacktrace I usually get from aws-sdk.
ResourceNotFoundException: Requested resource not found
at Request.extractError (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\protocol\json.js:52:27)
at Request.callListeners (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
at Request.emit (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
at Request.emit (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:688:14)
at Request.transition (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:22:10)
at AcceptorStateMachine.runTo (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\state_machine.js:14:12)
at D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\state_machine.js:26:10
at Request.<anonymous> (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:38:9)
at Request.<anonymous> (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:690:12)
at Request.callListeners (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:116:18)
My workaround is simply to catch async errors, and overwrite their stack traces. On the other hand, you may append Postgres stacktrace, or error message to your own errors.
async function getPersonFromDb (personId: string): Promise<DocumentClient.AttributeMap | undefined> {
const result = await documentClient.get({ // Similar to postgres.query()
TableName: 'wrong-name',
Key: { pk: personId, sk: personId }
}).promise().catch(error => {
Error.captureStackTrace(error)
throw error
})
return result.Item
}
test('Get a person from DynamoDB', async () => {
const person = await getPersonFromDb('hello')
expect(person).not.toBeUndefined()
})
// ========= new stacktrace ========
Error: Requested resource not found
at D:\workspaces\typescript-starters\console-app\test\abc.test.ts:12:13
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at getPersonFromDb (D:\workspaces\typescript-starters\console-app\test\abc.test.ts:8:20)
at Object.<anonymous> (D:\workspaces\typescript-starters\console-app\test\abc.test.ts:18:20) // my code, and where my error is thrown
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With