sidorares/node-mysql2 · error · TypeError

SSL profile must be an object, instead it's a ${typeof this.

Error message

SSL profile must be an object, instead it's a ${typeof this.ssl}

What it means

After resolving the `ssl` config option (a string profile name is looked up and returns an object; any other truthy value is used as-is), mysql2 requires the result to be an object. If `options.ssl` is truthy but not an object (e.g. the boolean `true`, a number, or an array), it throws. mysql2's SSL option must be either a string naming a built-in profile, an object of TLS options, or falsy.

Source

Thrown at lib/connection_config.js:166

        ? ConnectionConfig.getSSLProfile(options.ssl)
        : options.ssl || false;
    this.multipleStatements = options.multipleStatements || false;
    this.rowsAsArray = options.rowsAsArray || false;
    this.namedPlaceholders = options.namedPlaceholders || false;
    this.nestTables =
      options.nestTables === undefined ? undefined : options.nestTables;
    this.typeCast = options.typeCast === undefined ? true : options.typeCast;
    this.disableEval = Boolean(options.disableEval);
    this.enableCleartextPlugin = Boolean(options.enableCleartextPlugin);
    if (this.timezone[0] === ' ') {
      // "+" is a url encoded char for space so it
      // gets translated to space when giving a
      // connection string..
      this.timezone = `+${this.timezone.slice(1)}`;
    }
    if (this.ssl) {
      if (typeof this.ssl !== 'object') {
        throw new TypeError(
          `SSL profile must be an object, instead it's a ${typeof this.ssl}`
        );
      }
      // Default rejectUnauthorized to true
      this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
    }
    this.maxPacketSize = 0;
    this.charsetNumber = options.charset
      ? ConnectionConfig.getCharsetNumber(options.charset)
      : options.charsetNumber || Charsets.UTF8MB4_UNICODE_CI;
    this.compress = options.compress || false;
    this.authPlugins = options.authPlugins;
    this.authSwitchHandler = options.authSwitchHandler;
    this.clientFlags = ConnectionConfig.mergeFlags(
      ConnectionConfig.getDefaultFlags(options),
      options.flags || ''
    );
    // Default connection attributes

View on GitHub (pinned to 5ebe8903d6)

Solutions

  1. Pass an object of TLS options, e.g. `ssl: { rejectUnauthorized: true }`.
  2. Or pass a string naming a built-in SSL profile if one fits.
  3. To disable SSL explicitly, set `ssl: false` or omit it.

Example fix

// before
mysql.createConnection({ host, user, password, ssl: true });

// after
mysql.createConnection({ host, user, password, ssl: { rejectUnauthorized: true } });
Defensive patterns

Strategy: validation

Validate before calling

function normalizeSsl(ssl) {
  if (ssl === true || (ssl != null && typeof ssl !== 'object' && typeof ssl !== 'string')) {
    throw new TypeError('mysql2 ssl must be a string profile name or a TLS options object, not ' + typeof ssl);
  }
  return ssl;
}

Type guard

function isValidSslOption(ssl) {
  return ssl == null || typeof ssl === 'string' || (typeof ssl === 'object' && !Array.isArray(ssl));
}

Prevention

When it happens

Trigger: Passing `ssl: true` (accepted by some other MySQL libraries like `mysql`/`mysqljs`, but not by mysql2). Or passing a number or array. The value `true` becomes `this.ssl = true` and then fails the `typeof !== 'object'` check.

Common situations: Migrating code from the old `mysql` package which accepts `ssl: true`; setting `ssl: true` after reading a generic Node+MySQL tutorial; environment-driven config that resolves to a boolean.

Related errors


AI-assisted analysis of sidorares/node-mysql2@5ebe8903d6 (2026-08-03). Data as JSON: /data/errors/be58ad1e3cd00a76.json. Report an issue: GitHub.