sidorares/node-mysql2 · error · TypeError
SSL profile must be an object, instead it's a
Error message
SSL profile must be an object, instead it's a ${typeof this.ssl} What it means
After ConnectionConfig resolves the ssl option (lib/connection_config.js:146-172) — converting a string to an SSL profile and leaving other values as-is — it asserts that a truthy ssl is an object. A truthy non-object (e.g. a number, or a string that somehow bypassed conversion) indicates malformed config and throws a TypeError. A boolean true is an object-boxed Boolean? No — typeof true === 'boolean', so passing ssl: true would NOT trigger this (the code path makes ssl the boolean true only when options.ssl is absent/false); the throw fires for non-string, non-object truthy values.
Solutions
- Pass ssl as an object: ssl: { rejectUnauthorized: true } or as a known profile name string.
- Pass ssl: true for default TLS (the code accepts boolean true), or omit for no SSL.
- Sanitize env-derived ssl values: const ssl = process.env.SSL === 'true' ? { rejectUnauthorized: true } : false.
Example fix
// before
createConnection({ ssl: process.env.SSL_PORT }); // a number/string that is not a profile
// after
createConnection({ ssl: { rejectUnauthorized: true } }); Defensive patterns
Strategy: validation
Validate before calling
function normalizeSsl(ssl) {
if (ssl === true) return { rejectUnauthorized: true };
if (ssl === false || ssl == null) return false;
if (typeof ssl === 'string') return ssl; // profile name
if (typeof ssl === 'object') return ssl;
throw new TypeError(`ssl must be boolean|string|object, got ${typeof ssl}`);
}
// createConnection({ ..., ssl: normalizeSsl(rawSsl) }); Type guard
const isSslOption = (v) => v === true || v === false || typeof v === 'string' || (typeof v === 'object' && v !== null);
Prevention
- Always type the ssl config field explicitly (boolean | string | object).
- Sanitize env-derived ssl with an explicit normalize helper.
When it happens
Trigger: Passing ssl: 1 or ssl: 'true' where 'true' is not a known profile name (string branch resolves via getSSLProfile which would throw Unknown SSL profile first); passing a serialized JSON string that did not match a profile; passing an array as ssl.
Common situations: Reading ssl from an env var and coercing loosely (ssl: Number(process.env.SSL)); passing a config object built by a helper that returns a non-object on a missing key.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Unknown SSL profile
- "database" connection config property must be a string
- Unknown charset
- "user" connection config property must be a string
- Bind parameters must be array if namedPlaceholders…
AI-assisted analysis of sidorares/node-mysql2@8b1f829d37 (2026-08-11).
Data as JSON: /api/errors/be58ad1e3cd00a76.
Report an issue: GitHub.
Appendix: 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 attributesView on GitHub (pinned to 8b1f829d37)