{"record":{"id":"3385e4b62e8c8153","repo":"sidorares/node-mysql2","slug":"database-connection-config-property-must-be-a-st-3385e4","errorCode":null,"errorMessage":"\"database\" connection config property must be a string","messagePattern":"\"database\" connection config property must be a string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/packets/handshake_response.js","lineNumber":129,"sourceCode":"      }\n      packet.writeLengthCodedNumber(keysLength);\n      for (k = 0; k < attrNames.length; ++k) {\n        packet.writeLengthCodedString(attrNames[k], encoding);\n        packet.writeLengthCodedString(\n          connectAttributes[attrNames[k]],\n          encoding\n        );\n      }\n    }\n    return packet;\n  }\n\n  toPacket() {\n    if (typeof this.user !== 'string') {\n      throw new Error('\"user\" connection config property must be a string');\n    }\n    if (typeof this.database !== 'string') {\n      throw new Error('\"database\" connection config property must be a string');\n    }\n    // dry run: calculate resulting packet length\n    const p = this.serializeResponse(Packet.MockBuffer());\n    return this.serializeResponse(Buffer.alloc(p.offset));\n  }\n  static fromPacket(packet, serverFlags = 0xffffffff) {\n    const args = {};\n    args.clientFlags = packet.readInt32();\n    function isSet(flag) {\n      return args.clientFlags & serverFlags & ClientConstants[flag];\n    }\n    args.maxPacketSize = packet.readInt32();\n    args.charsetNumber = packet.readInt8();\n    const encoding = CharsetToEncoding[args.charsetNumber];\n    args.encoding = encoding;\n    packet.skip(23);\n    args.user = packet.readNullTerminatedString(encoding);\n    let authTokenLength;","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/sidorares/node-mysql2/blob/8b1f829d3706404ab372cf97bd77ebcf86578d97/lib/packets/handshake_response.js#L111-L147","documentation":"Sibling of the `user` guard, thrown by HandshakeResponse.toPacket() when serializing the database name into the handshake packet (only when CONNECT_WITH_DB is negotiated). The constructor's this.database = handshake.database || '' only coerces falsy values, so a truthy non-string survives to this typeof check and aborts the handshake mid-connect.","triggerScenarios":"Passing a truthy non-string as `database`: createConnection({ database: 3306 }) (port value misplaced), createPool({ database: ['app'] }), or a value loaded from a schema where the field was typed as a number/object.","commonSituations":"Config typos putting a port or pool size into the database field; YAML/JSON where an unquoted numeric database name parses as a number; ORM migrations that construct config objects programmatically with the wrong field.","solutions":["Cast the value to a string: database: String(opts.database).","Validate the config object with a schema (zod, joi) before connecting.","Correct the upstream source so `database` is always a string."],"exampleFix":"// before\ncreateConnection({ host: 'localhost', database: 123 });\n// after\ncreateConnection({ host: 'localhost', database: '123' });","handlingStrategy":"type-guard","validationCode":"function normalizeConnectionConfig(opts) {\n  if ('database' in opts && opts.database != null && typeof opts.database !== 'string') {\n    opts = { ...opts, database: String(opts.database) };\n  }\n  return opts;\n}\n\nconst safeOpts = normalizeConnectionConfig(rawOpts);\nconst conn = await createConnection(safeOpts);","typeGuard":"function isValidDatabase(opt) {\n  return opt == null || typeof opt === 'string';\n}\n\nif (!isValidDatabase(opts.database)) {\n  throw new TypeError(`database must be a string, got ${typeof opts.database}`);\n}","tryCatchPattern":null,"preventionTips":["Validate the config schema before connecting; fail at startup, not during the handshake.","Quote numeric database names in JSON/YAML to keep them strings.","Double-check field placement in config builders (port vs database)."],"tags":["config","validation","type-mismatch"],"backgroundTag":null,"analyzedSha":"8b1f829d3706404ab372cf97bd77ebcf86578d97","analyzedAt":"2026-08-11T02:54:28.964Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}