Skip to content

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

@Idriosiris

Description

@Idriosiris

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions