Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AssertionError [ERR_ASSERTION]: req (object) is required #241

Open
Idriosiris opened this issue Jul 18, 2022 · 1 comment
Open

AssertionError [ERR_ASSERTION]: req (object) is required #241

Idriosiris opened this issue Jul 18, 2022 · 1 comment

Comments

@Idriosiris
Copy link

Idriosiris commented Jul 18, 2022

Hello everyone,

Sorry if this was ever raised before but I couldn't find any obviously similar issues.

So, in one of our NodeJS applications using restify with restify-clients we can spot the following error which causes the apps container to restart.

AssertionError [ERR_ASSERTION]: req (object) is required
    at Object.createConnectTimeoutErr (/app/node_modules/restify-clients/lib/helpers/errors.js:37:12)
    at Timeout.connectTimeout (/app/node_modules/restify-clients/lib/HttpClient.js:270:30)
    at Shim.applySegment (/app/node_modules/newrelic/lib/shim/shim.js:1412:20)
    at Timeout.wrappedCallback [as _onTimeout] (/app/node_modules/newrelic/lib/shim/shim.js:1288:21)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7) {
  generatedMessage: false,
  code: 'ERR_ASSERTION',
  actual: 'undefined',
  expected: 'object',
  operator: '==='
}

As per the error message, the second line in the function below seems to blow up as there is no req object at the time of the callback.

function createConnectTimeoutErr(opts, req) {
    assert.object(opts, 'opts');
    assert.object(req, 'req');

    var errInfo = createErrInfo(opts, req);
    var errMsg;
    var errName;

That is only called in the rawRequest() method in the bit, which prepares the connection timeout errors and the rest of the behaviour. A code snippet of that is here:

if (opts.connectTimeout) {
        connectionTimer = setTimeout(function connectTimeout() {
            connectionTimer = null;

            // build connect timeout error using current request options, do
            // this first before we abort the request so we can pick up socket
            // information like the ip.
            var err = errors.createConnectTimeoutErr(opts, req);
            req._forcedAbortErr = err;
            req.abort();
        }, opts.connectTimeout);
    }

With that in mind, we could assume that somehow that req object is not created or is somehow lost which causes the failure of the assertion.

Looking at the code documentation of the rawRequest method we can see the following phrase -> "In short, the callback should only ever be called once, with the two known scenarios: 1) A ConnectionTimeout/DNSTimeoutError occurs, and the connection is never established, and the request object is never created"

Sorry if I'm reading this wrong, but from my understanding, a req is never created as a connection is never established in the case of a connection timeout. If that is the case, why is the req asserted against when handling a connection timeout err?

Again, sorry if I'm reading this wrong but this is a problem occurring in production and we have not been able to replicate it in the pre-production environment. Did load-testing with similar traffic to prod and the configurations should be the same as we run the container from the same image.

Below you have a couple more configuration options that we use:

function httpClient(baseUrl, headers) {
	headers.accept = 'application/json';
	headers.host = '';

	return restifyClients.createJsonClient({
		url: baseUrl,
		headers,
		userAgent: headers['user-agent'],
		connectTimeout: 10000,
		requestTimeout: 10000,
		retry: false
	});
}

Is this something anyone else experienced before? What else might cause such behaviour if the code above is correct?

@Idriosiris
Copy link
Author

Idriosiris commented Jul 19, 2022

Quick update, taking out the connectTimeout: 10000 seems to have fixed the problem. In theory, I think that should just fall back to the nodejs socket timeout which shouldn't change the behaviour in case of a timeout.

What I think happens is that the code mentioned above doesn't execute anymore as the if on the opts.connectTimeout evaluates to false and somehow the connection timeout error is handled in another way which doesn't critically fails anymore. Not sure where that logic is, haven't got the chance to dig deeper.

This would suggest that although we might have a connection failing the code manages to deal with it a lot smoother when a connectTimeout is not passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant