bcrypt
semver
>=5.0.0 <7.0.0postconditions25functions7last verified2026-06-24coverage score100%Postconditions: what we check
- hash · invalid-argserrorWhendata or salt is null/undefined, or data is not a string/Buffer, or salt is not a string or numberThrows
Error with message 'data and salt arguments required' or 'data must be a string or Buffer and salt must either be a salt string or a number of rounds'Required handlingCaller MUST validate inputs before calling bcrypt.hash(). Wrap calls in try-catch (synchronous throw path) or use .catch() / try-await-catch for the Promise path. Unhandled rejections will crash the process in Node.js.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - hash · hashing-errorerrorWhenAn error occurs during the native bcrypt hashing operation (e.g., native module failure)Throws
Error — rejected Promise or callback first argumentRequired handlingCaller MUST wrap bcrypt.hash() in try-catch when using async/await, or provide an error-checking callback. Unhandled rejections will crash the process.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - hash · hash-invalid-callbackerrorWhenA third argument is passed as the callback but is not a function (e.g., a string, object, or number). Returns a rejected Promise regardless of whether data and salt are valid.Throws
Rejected Promise with Error('cb must be a function or null to return a Promise'). This is a programmer error — the rejection fires synchronously before any hashing occurs.Required handlingCaller MUST either omit the callback (use async/await) or ensure cb is a function. Passing a non-function third argument is a programming error that produces a rejected promise. Wrap the call in try-catch or handle with .catch().costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - hash · hash-callback-position-swapwarningWhenThe first or second positional argument to bcrypt.hash() is itself a function (typeof === 'function'). Common cause: registration flows refactored from callback to promise style where the cb was left in the data or salt slot, or a helper that intended to return a salt value accidentally returns a function reference.Throws
Does NOT reject any Promise — none is constructed. bcrypt SYNCHRONOUSLY invokes the mispositioned function with Error('data must be a string or Buffer and salt must either be a salt string or a number of rounds') via process.nextTick. The return value of bcrypt.hash() is undefined; `await bcrypt.hash(fn, 10)` resolves to undefined. The Error reaches the misplaced function but not the await-scope try-catch.Required handlingCallers MUST validate that data is a string/Buffer BEFORE the call — a try-catch around `await bcrypt.hash(...)` will NOT catch this misuse. In a registration handler, the downstream symptom is that `await bcrypt.hash(plaintext, 10)` returns undefined, which then gets persisted to the user record as a null/undefined password hash. Subsequent login attempts route through bcrypt.compare(plaintext, undefined) and fail with a different error path — the original misuse is invisible at the registration site.costhighin prodsilent failureusers seelost datavisibilitysilentSources[1] - hash · successinfoWhenHashing completes successfullyReturnsPromise<string> resolving to the bcrypt hash string (60 characters)Required handlingNo action required — use the returned value as needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2]
- compare · invalid-argserrorWhendata or hash is null/undefined, or data is not a string/Buffer, or hash is not a stringThrows
Async path (Promise): rejects with Error('data and hash arguments required') if either arg is null/undefined, or Error('data and hash must be strings') for type mismatches (v6.0.0 source line 211 — message differs from compareSync which still emits the longer 'data must be a string or Buffer and hash must be a string' form on line 166).Required handlingCaller MUST validate that both arguments are present and of the correct type. Wrap calls in try-catch or use .catch() on the returned Promise. Note: error.message text differs between sync and async paths in v6 — do not assert on exact message text across paths.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - compare · comparison-errorerrorWhenAn error occurs during the native bcrypt comparison (e.g., malformed hash string)Throws
Error — rejected Promise or callback first argumentRequired handlingCaller MUST wrap bcrypt.compare() in try-catch when using async/await. A malformed hash string causes an error, not a false return value.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - compare · compare-invalid-callbackerrorWhenA third argument is passed as the callback but is not a function (e.g., a string, object, or number). Returns a rejected Promise regardless of whether data and hash are valid.Throws
Rejected Promise with Error('cb must be a function or null to return a Promise'). This is a programmer error.Required handlingCaller MUST either omit the callback (use async/await) or ensure cb is a function. Wrap the call in try-catch or handle with .catch().costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - compare · compare-callback-position-swapwarningWhenThe first or second positional argument to bcrypt.compare() is itself a function (typeof === 'function'). Common cause: callers refactoring from callback→promise styles who accidentally leave the callback in the data or hash slot, or callers passing an unawaited helper that returns a function.Throws
Does NOT reject any Promise — none is constructed. Instead, bcrypt SYNCHRONOUSLY invokes the mispositioned function with an Error('data and hash arguments required') via process.nextTick. The return value of bcrypt.compare() in this branch is undefined; `await bcrypt.compare(fn, hash)` resolves to undefined. The Error reaches the misplaced function but not the await-scope try-catch.Required handlingCallers MUST validate that both positional arguments are strings/Buffers BEFORE the call — a try-catch around `await bcrypt.compare(...)` will NOT catch this misuse. The downstream symptom in an auth check is silent rejection of valid credentials: `if (await bcrypt.compare(plaintext, storedHash))` evaluates the undefined return as falsy, denying access to users whose credentials would otherwise match. The misfired callback's Error lands in whichever scope owns the function value, which is rarely the auth-check scope.costmediumin prodsilent failureusers seeauthentication failurevisibilitysilentSources[1] - compare · mismatchinfoWhenThe plain-text data does not match the hashReturnsPromise<false> — resolves to boolean falseRequired handlingNo action required — use the returned value as needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2]
- compare · matchinfoWhenThe plain-text data matches the hashReturnsPromise<true> — resolves to boolean trueRequired handlingNo action required — use the returned value as needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2]
- genSalt · invalid-roundserrorWhenrounds parameter is provided but is not a numberThrows
Error with message 'rounds must be a number'Required handlingCaller MUST ensure rounds is a number when provided. Wrap in try-catch or use .catch() on the returned Promise.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - genSalt · invalid-minorerrorWhenminor version parameter is provided but is not 'a' or 'b'Throws
Error with message 'minor must be either a or b'Required handlingOnly pass 'a' or 'b' as the minor version. The default ('b') is recommended for new code.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - genSalt · gen-salt-entropy-errorerrorWhenNode.js crypto.randomBytes() fails to generate random bytes — typically due to system entropy exhaustion in containerized or virtualized environments (rare but real in CI/CD and Docker).Throws
Rejected Promise (or callback error) with the Error from crypto.randomBytes(). Error message varies by OS — commonly 'Error generating random bytes' or similar.Required handlingCaller MUST wrap bcrypt.genSalt() in try-catch or use .catch(). While rare in production, entropy exhaustion is a known failure mode in ephemeral containers and edge deployments. In registration flows, a failure here means the user cannot create an account — treat as a retriable error.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - genSalt · successinfoWhenSalt generation succeedsReturnsPromise<string> resolving to the generated salt stringRequired handlingNo action required — use the returned value as needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2]
- hashSync · hash-sync-invalid-argserrorWhendata or salt is null/undefined, or data is not a string/Buffer, or salt is not a string or numberThrows
Error('data and salt arguments required') if either arg is null/undefined; Error('data must be a string or Buffer and salt must either be a salt string or a number of rounds') for type mismatches. Throws synchronously — not a rejected Promise.Required handlingCaller MUST validate inputs before calling bcrypt.hashSync(). Wrap in try-catch since this is a synchronous throw (not a rejected Promise). A missing try-catch will propagate the exception up the call stack — in Express, this crashes the request handler unless a global error boundary catches it.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - hashSync · hash-sync-event-loop-blockwarningWhenCalled in a web server request handler with saltRounds >= 10Throws
Does not throw — but blocks the Node.js event loop for 100ms–1s+ per callRequired handlingDO NOT call bcrypt.hashSync() inside Express/Fastify/Next.js route handlers or any code on the request/response hot path. Use the async bcrypt.hash() instead. Blocking the event loop during password hashing causes ALL concurrent HTTP requests to queue, leading to cascading latency under load. This is a behavioral correctness issue, not just a performance concern.costhighin proddegraded serviceusers seedegraded performancevisibilityvisibleSources[2] - compareSync · compare-sync-invalid-argserrorWhendata or hash is null/undefined, or data is not a string/Buffer, or hash is not a stringThrows
Error('data and hash arguments required') if either arg is null/undefined; Error('data must be a string or Buffer and hash must be a string') for type mismatches. Throws synchronously.Required handlingCaller MUST validate inputs before calling bcrypt.compareSync(). Wrap in try-catch. A malformed hash string (e.g., not a valid bcrypt hash) will cause this function to throw — it does NOT return false for an invalid hash format.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - compareSync · compare-sync-event-loop-blockwarningWhenCalled in a web server request handlerThrows
Does not throw — but blocks the Node.js event loop for 100ms–1s+ per callRequired handlingDO NOT call bcrypt.compareSync() inside Express/Fastify/Next.js route handlers. Use bcrypt.compare() (async) instead. During login endpoints under load, using compareSync serializes all auth checks — each login queues behind the previous one, causing login latency to multiply linearly with concurrent users.costhighin proddegraded serviceusers seedegraded performancevisibilityvisibleSources[2] - genSaltSync · gen-salt-sync-invalid-roundserrorWhenrounds parameter is provided but is not a number (e.g., a string)Throws
Error('rounds must be a number'). Throws synchronously.Required handlingCaller MUST ensure rounds is a number when provided. Wrap in try-catch. Note: falsy values (0, null, undefined) are silently coerced to the default 10 rounds — only non-number, truthy values throw.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - genSaltSync · gen-salt-sync-invalid-minorerrorWhenminor parameter is provided but is not 'a' or 'b'Throws
Error('minor must be either "a" or "b"'). Throws synchronously.Required handlingOnly pass 'a' or 'b' as the minor version. Omit the parameter to use the default 'b'. Passing any other string causes an immediate synchronous throw.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - genSaltSync · gen-salt-sync-successinfoWhenSalt generation succeedsReturnsstring — a bcrypt salt in the format '$2b$<rounds>$<22-char-base64-salt>' (29 characters total). This salt string is passed directly to bcrypt.hashSync().Required handlingNo action required — use the returned salt string as input to hashSync() or hash().costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2]
- getRounds · get-rounds-missing-hasherrorWhenhash argument is null or undefinedThrows
Error('hash argument required'). Throws synchronously.Required handlingCaller MUST check that the hash argument exists before calling getRounds(). Wrap in try-catch. Common failure pattern: calling getRounds() during hash migration/audit over DB rows where some rows have null password fields.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - getRounds · get-rounds-invalid-typeerrorWhenhash argument is not a string (e.g., a Buffer or number)Throws
Error('hash must be a string'). Throws synchronously.Required handlingCaller MUST ensure the hash is a string. Wrap in try-catch. Common failure pattern: passing a Buffer or TypeScript typed value that hasn't been .toString()'d before passing to getRounds().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - getRounds · get-rounds-successinfoWhenhash argument is a valid bcrypt hash stringReturnsnumber — the integer cost factor (rounds) embedded in the hash string. Extracted from the hash format: '$2b$<cost>$...'. For most production hashes, returns 10-12.Required handlingNo action required. Compare the returned number against your current minimum rounds policy (e.g., if returned value < 12, trigger a rehash on next login to upgrade security).costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
Official documentation
- [3]nodejs.org/api/crypto.htmlCrypto
Source code
- [1]github.com/kelektiv/node.bcrypt.js/blobkelektiv/node.bcrypt.js · bcrypt.js
- [2]github.com/kelektiv/node.bcrypt.js/blobkelektiv/node.bcrypt.js · README.md
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sources: bcrypt
Official Documentation
Research Date: 2026-02-26
Need a different package?
Request a profile