tarn.js: Operation timed out for an unknown reason

I have a web app that keeps crashing with this error:

  • 2020-01-23T08:07:36.485-05:00 [APP/PROC/WEB/0] [ERR] (node:134) UnhandledPromiseRejectionWarning: Error: operation timed out for an unknown reason
  • 2020-01-23T08:07:36.485-05:00 [APP/PROC/WEB/0] [ERR] at /home/vcap/app/node_modules/tarn/lib/PendingOperation.js:16:27
  • 2020-01-23T08:07:36.485-05:00 [APP/PROC/WEB/0] [ERR] (node:134) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 140)

Searched far and wide but can’t pinpoint the exact database call that’s triggering this. Attempts to resolve have included specifying Node version 13.5.0, increasing max pool size, updating all npm packages.

Any help is appreciated.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 15 (1 by maintainers)

Most upvoted comments

Hi, i’m facing the same issue,

Error: operation timed out for an unknown reason
at PendingOperation.promise.timeout.catch.err (/app/node_modules/tarn/lib/PendingOperation.js:16:27)
t propagateAslWrapper (/app/node_modules/async-listener/index.js:504:23)
at /app/node_modules/async-listener/glue.js:188:31
at /app/node_modules/async-listener/index.js:541:70
at /app/node_modules/async-listener/glue.js:188:31

this is only happening when Query is fired simultaneously and during this operation network connectivity is dropped, once network is back same error is keep on coming, until service restarted and new connection established.

to reproduce this following config :

const configDB = {
  user: config.sqlDbUsername,
  password: config.sqlDbPassword,
  port: config.sqlDbPort,
  server: config.sqlDbHost,
  database: config.sqlDbName,
  pool: {
    max: 1,
  },
};
let _connection: Promise<sql.ConnectionPool>;
export const setupDB = () => {
  try {
    const _pool = new sql.ConnectionPool(configDB);
    _connection = _pool.connect();
    logger.info('DB Connection is ready ...');
    _pool.on('error', error => {
      logger.error('DB Error handler :', error);
    });
  } catch (err) {
    logger.error('Failed to Initialize the socket:', err);
    throw err;
  }
};
export const getConnectionPool = () => {
  return _connection;
};

async function fetchData() {
  const _pool = await getConnectionPool();
  const _request = new PreparedStatement(_pool);
  await _request.prepare(query); // pass sample query
  const { recordsets } = await _request.execute(data);
  await _request.unprepare();
  return recordsets;
}

I’m executing parallel query using prepare statement, and with pool.max is 1

@laychopy I’ve handled this issue with different approach, i’ve listen for the error event (https://github.com/tediousjs/node-mssql#connect-callback) along with Error code ETIMEOUT, and again retry the connection within some interval, so every time if i’ll get operation timed out with error code, it will keep on retry connection until success ,

Here is the sample code

const handleDBError = (error: sql.ConnectionError) => {
  logger.error('DB Error handler: ', error);
  if (error.message.includes('operation timed out') || error.code === 'ETIMEOUT') {
    clearInterval(timer);
    timer = setInterval(() => {
      return void (async () => {
        try {
          logger.info(`Retrying connection ... `);
          await setupDB();
        } catch (error) {
          logger.error('Error connecting ...');
        }
      })();
    }, config.retryConnectionInterval);
  }
};

export const setupDB = async () => {
  try {
    _pool = new sql.ConnectionPool(configDB);
    await _pool.connect();
    clearInterval(timer); // clear the interval once the connection established
    logger.info('DB Connection successful ...');
    _pool.on('error', handleDBError);
  } catch (err) {
    logger.error('Failed to connect:', err);
    const _err = <sql.ConnectionError>err;
    if (_err.code === 'ETIMEOUT') handleDBError(err);
    throw err;
  }
};

Hope this helps you