{"record":{"id":"b0ccf4ec52eddf42","repo":"brianc/node-postgres","slug":"buffers-cannot-be-empty","errorCode":null,"errorMessage":"Buffers cannot be empty","messagePattern":"Buffers cannot be empty","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/pg/lib/crypto/sasl.js","lineNumber":252,"sourceCode":"    throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature must be base64')\n  }\n  return {\n    serverSignature,\n  }\n}\n\nfunction xorBuffers(a, b) {\n  if (!Buffer.isBuffer(a)) {\n    throw new TypeError('first argument must be a Buffer')\n  }\n  if (!Buffer.isBuffer(b)) {\n    throw new TypeError('second argument must be a Buffer')\n  }\n  if (a.length !== b.length) {\n    throw new Error('Buffer lengths must match')\n  }\n  if (a.length === 0) {\n    throw new Error('Buffers cannot be empty')\n  }\n  return Buffer.from(a.map((_, i) => a[i] ^ b[i]))\n}\n\nmodule.exports = {\n  startSession,\n  continueSession,\n  finalizeSession,\n  DEFAULT_MAX_SCRAM_ITERATIONS,\n}\n","sourceCodeStart":234,"sourceCodeEnd":263,"githubUrl":"https://github.com/brianc/node-postgres/blob/ff9d775abd12f29dd6df03945253b54eabbb29f2/packages/pg/lib/crypto/sasl.js#L234-L263","documentation":"Thrown by xorBuffers() when both input Buffers have length 0. This function XORs two equal-length Buffers to compute the client proof during SCRAM authentication. Since it operates on HMAC-SHA256 outputs (always 32 bytes), empty buffers are impossible under correct crypto operation — this guard fires only if the crypto layer returned empty data.","triggerScenarios":"xorBuffers() is called at sasl.js:120 with Buffer.from(clientKey) and Buffer.from(clientSignature), both of which are outputs of crypto.hmacSha256(). HMAC-SHA256 always produces 32 bytes. If either Buffer is empty (length 0), the check at line 251-252 fires. This would require the crypto module's hmacSha256 to return an empty ArrayBuffer/Uint8Array.","commonSituations":"A broken or non-standard crypto implementation — e.g., a mock or stub in tests, a polyfill that doesn't correctly implement HMAC-SHA256, or a corrupted Node.js installation. Not reachable with Node.js's built-in crypto module under normal conditions.","solutions":["If using a custom crypto shim or polyfill in packages/pg/lib/crypto/utils.js, ensure hmacSha256 returns a correct 32-byte output.","Verify Node.js crypto is functioning correctly — run a simple HMAC test outside of pg.","Reinstall node-postgres cleanly to restore the default crypto implementation.","In test environments, ensure any crypto mocks return realistic 32-byte outputs."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify crypto module is functional (relevant for test/custom environments):\nconst crypto = require('crypto')\nconst result = crypto.createHmac('sha256', 'key').update('Client Key').digest()\nif (result.length !== 32) {\n  throw new Error('HMAC-SHA256 is broken in this environment')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.connect()\n} catch (err) {\n  if (err.message.includes('Buffers cannot be empty')) {\n    // Crypto module is returning empty output — environment or crypto shim issue\n    throw new Error('Internal crypto failure — verify Node.js crypto module is intact')\n  }\n  throw err\n}","preventionTips":["Do not use custom crypto shims or polyfills that don't correctly implement HMAC-SHA256.","In test environments, ensure crypto mocks return realistic 32-byte outputs.","Verify Node.js installation integrity if this error appears unexpectedly.","Keep node-postgres's internal crypto module unmodified."],"tags":["authentication","sasl","scram","crypto","internal-invariant"],"backgroundTag":null,"analyzedSha":"ff9d775abd12f29dd6df03945253b54eabbb29f2","analyzedAt":"2026-08-11T15:33:59.644Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}