brianc/node-postgres · error · Error
Buffers cannot be empty
Error message
Buffers cannot be empty
What it means
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.
Source
Thrown at packages/pg/lib/crypto/sasl.js:252
throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature must be base64')
}
return {
serverSignature,
}
}
function xorBuffers(a, b) {
if (!Buffer.isBuffer(a)) {
throw new TypeError('first argument must be a Buffer')
}
if (!Buffer.isBuffer(b)) {
throw new TypeError('second argument must be a Buffer')
}
if (a.length !== b.length) {
throw new Error('Buffer lengths must match')
}
if (a.length === 0) {
throw new Error('Buffers cannot be empty')
}
return Buffer.from(a.map((_, i) => a[i] ^ b[i]))
}
module.exports = {
startSession,
continueSession,
finalizeSession,
DEFAULT_MAX_SCRAM_ITERATIONS,
}
View on GitHub (pinned to ff9d775abd)
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify crypto module is functional (relevant for test/custom environments):
const crypto = require('crypto')
const result = crypto.createHmac('sha256', 'key').update('Client Key').digest()
if (result.length !== 32) {
throw new Error('HMAC-SHA256 is broken in this environment')
} Try / catch
try {
await client.connect()
} catch (err) {
if (err.message.includes('Buffers cannot be empty')) {
// Crypto module is returning empty output — environment or crypto shim issue
throw new Error('Internal crypto failure — verify Node.js crypto module is intact')
}
throw err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- SASL: SCRAM-SERVER-FINAL-MESSAGE: serverData must be a strin
- SASL: text must be a string
- SASL: attribute pairs text must be a string
- SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not
- SASL: Invalid attribute pair entry
AI-assisted analysis of brianc/node-postgres@ff9d775abd (2026-08-11).
Data as JSON: /api/errors/b0ccf4ec52eddf42.
Report an issue: GitHub.