bcryptjs
semver
>=2.0.0postconditions22functions9last verified2026-06-19coverage score100%Postconditions — what we check
- hash · hash-type-errorerrorWhenpassword is not a string or Buffer, or salt is invalid typeThrows
Error: Illegal arguments: [actual_type], [actual_type]Required handlingCaller MUST wrap bcrypt.hash() in try-catch block or use .catch() handler. Type errors occur when forgetting await on Promise or passing wrong types. Validate input types before calling hash() to provide better error messages.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - hash · hash-invalid-salterrorWhensalt parameter is not a string, number, or valid salt formatThrows
Error: Invalid salt version or Illegal argumentsRequired handlingCaller MUST handle errors from invalid salt parameter. Use genSalt() to generate valid salts, or pass numeric salt rounds (recommended: 12).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - hash · hash-rounds-out-of-rangeerrorWhensalt rounds < 4 or > 31Throws
Error: Rounds out of range (4-31)Required handlingCaller MUST validate salt rounds are between 4 and 31. Production systems should use rounds >= 12 for adequate security.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - hash · hash-internal-failureerrorWheninternal hashing operation failsThrows
ErrorRequired handlingCaller MUST handle unexpected errors from hash() operation. While rare, internal failures can occur and should not crash the application.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - compare · compare-type-errorerrorWhenpassword or hash parameter is not a stringThrows
Error: Illegal arguments: [actual_type], [actual_type]Required handlingCaller MUST wrap bcrypt.compare() in try-catch or use .catch() handler. Type errors commonly occur when retrieving hash from database as Buffer instead of string, or when password input is undefined/null.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - compare · compare-invalid-hasherrorWhenhash parameter is not a valid bcrypt hash formatThrows
Error: Invalid hash provided or hash is not a valid bcrypt hashRequired handlingCaller MUST handle errors from malformed hash values. Database corruption, string truncation (VARCHAR < 60), or encoding issues can cause invalid hashes. This is the #1 production authentication bug.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - compare · compare-internal-failureerrorWheninternal comparison operation failsThrows
ErrorRequired handlingCaller MUST handle unexpected errors from compare() operation. Errors should not be silently swallowed as they may indicate security issues or data corruption.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - genSalt · gensalt-invalid-roundserrorWhenrounds parameter < 4 or > 31Throws
Error: Rounds out of range (4-31)Required handlingCaller MUST wrap genSalt() in try-catch or use .catch() handler when rounds parameter could be invalid. Validate rounds before calling.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - genSalt · gensalt-type-errorerrorWhenrounds parameter is not a numberThrows
Error: Illegal arguments: [actual_type]Required handlingCaller MUST validate rounds is a number. Common error when reading from environment variables or config files without parsing to integer.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - genSalt · gensalt-rng-failureerrorWhenrandom number generator fails (browser context without setRandomFallback)Throws
Error: Secure random number generator not availableRequired handlingCaller MUST handle RNG failures. In browser environments, call bcrypt.setRandomFallback() to provide a CSPRNG fallback.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[8] - hashSync · hash-sync-type-errorerrorWhenpassword is not a string or salt is not a string/numberThrows
Error: Illegal arguments: [typeof password], [typeof salt]Required handlingCaller MUST wrap hashSync() in a try-catch block. Type errors throw synchronously. Most common cause: passing undefined/null password (unvalidated input) or an already-hashed password Buffer from a database query instead of a string. Unlike the async hash(), there is no .catch() available — only try-catch.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - hashSync · hash-sync-rounds-out-of-rangeerrorWhensalt is a number and rounds < 4 or > 31Throws
Error: Illegal number of rounds (4-31): [N]Required handlingCaller MUST wrap hashSync() in try-catch when rounds parameter comes from configuration or environment variables. Validate rounds is 4-31 before calling. Production minimum recommended: 12.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - hashSync · hash-sync-blocks-event-looperrorWhenhashSync() is called in a Node.js HTTP request handler or any async contextThrows
Does not throw — instead blocks event loop for 100ms-400ms+Required handlingCaller MUST NOT use hashSync() in Express/Fastify/Next.js API routes, background workers serving concurrent requests, or any code running in the main event loop. The operation blocks all other requests for its duration. Use async hash() instead. hashSync is ONLY appropriate in: CLI scripts, database seed files, one-time migration scripts, and test setup (beforeAll/beforeEach fixtures).costhighin proddegraded serviceusers seeservice unavailablevisibilityvisibleSources[10] - compareSync · compare-sync-type-errorerrorWhenpassword or hash is not a stringThrows
Error: Illegal arguments: [typeof password], [typeof hash]Required handlingCaller MUST wrap compareSync() in try-catch. Common cause: retrieving hash from database as Buffer instead of string, or passing undefined when the user record is not found. Unlike the async compare(), no .catch() is available.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - compareSync · compare-sync-silent-false-on-bad-hasherrorWhenhash parameter is a string but not exactly 60 characters (malformed bcrypt hash)Returnsfalse — NOT an error, not a throw. Silent authentication failure.Required handlingCallers who only check `if (isMatch)` without validating that the stored hash is well-formed will silently deny authentication for ALL users whose hashes were truncated, corrupted, or stored in a VARCHAR(40) column. Always validate that the hash column is VARCHAR(60) or CHAR(60) in the database schema and that the hash was not corrupted in transit. This is the #1 silent authentication bug with bcryptjs — the function returns false for wrong-password AND bad-hash, making it impossible to distinguish them without additional checks.costhighin prodsilent failureusers seeauthentication failurevisibilitysilent
- compareSync · compare-sync-blocks-event-looperrorWhencompareSync() is called in a Node.js HTTP request handler or async contextThrows
Does not throw — instead blocks event loop for 100ms-400ms+Required handlingCaller MUST NOT use compareSync() in Express/Fastify/Next.js API routes or any code running in the main event loop. Use async compare() for all authentication endpoints. compareSync is ONLY appropriate in: CLI scripts, test setup, and one-off verification scripts.costhighin proddegraded serviceusers seeservice unavailablevisibilityvisibleSources[10] - genSaltSync · gensalt-sync-invalid-roundserrorWhenrounds is not a number, or rounds < 4 or rounds > 31Throws
Error: Illegal arguments: [typeof rounds] (wrong type) or Error: Illegal number of rounds (4-31): [N] (out of range)Required handlingCaller MUST wrap genSaltSync() in try-catch when rounds comes from configuration or user input. Validate rounds is an integer between 4 and 31. Common error: reading BCRYPT_ROUNDS from environment variable as string without parseInt() — e.g., process.env.BCRYPT_ROUNDS returns '12' (string) not 12 (number).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - genSaltSync · gensalt-sync-rng-failureerrorWhencalled in a browser environment without setting a random fallback via setRandomFallback()Throws
Error: Secure random number generator not availableRequired handlingIn browser environments, bcryptjs requires calling bcrypt.setRandomFallback() with a CSPRNG implementation before using any salt-generating functions. Node.js environments use crypto.randomBytes() automatically and are unaffected.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - getRounds · get-rounds-type-errorerrorWhenhash parameter is not a stringThrows
Error: Illegal arguments: [typeof hash]Required handlingCaller MUST wrap getRounds() in try-catch when the hash comes from a database column or external source where it could be null, undefined, a Buffer, or any non-string type. Common cause: the user record was not found (hash is undefined) and the calling code did not guard, so a synchronous throw bubbles up into a login or password-rotation handler that does not expect it. Validate that the hash is a string of length 60 before calling getRounds().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - getSalt · get-salt-type-errorerrorWhenhash parameter is not a stringThrows
Error: Illegal arguments: [typeof hash]Required handlingCaller MUST wrap getSalt() in try-catch when the hash comes from a database row or external source where it may be null, undefined, or a non-string type (Buffer, Object). The function throws synchronously — there is no Promise and no .catch() path. Validate that the hash is a 60-character string before calling.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - getSalt · get-salt-illegal-lengtherrorWhenhash is a string but its length is not exactly 60 charactersThrows
Error: Illegal hash length: [length] != 60Required handlingCaller MUST handle the length-validation throw. Common cause: the hash was stored in a VARCHAR column narrower than 60 (e.g. VARCHAR(40)), or it was trimmed/encoded on insert, or it was migrated from a different bcrypt variant (some libraries produce $2y$ hashes that may have different lengths). Unlike compareSync() which silently returns false for malformed hashes, getSalt() throws explicitly — so an uncaught throw will crash the handler. Validate hash.length === 60 before calling, or wrap the call.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - truncates · truncates-type-errorerrorWhenpassword parameter is not a stringThrows
Error: Illegal arguments: [typeof password]Required handlingCaller MUST wrap truncates() in try-catch or validate the input is a string first. Common cause: passing undefined when the user-submitted form field is missing, or passing a Buffer from a binary upload path. The function is synchronous — there is no Promise rejection or .catch() handler available.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9]
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]github.com/dcodeIO/bcrypt.jshttps://github.com/dcodeIO/bcrypt.js/issues/146
- [2]github.com/dcodeIO/bcrypt.jshttps://github.com/dcodeIO/bcrypt.js/issues/20
- [3]github.com/kelektiv/node.bcrypt.jshttps://github.com/kelektiv/node.bcrypt.js/issues/898
- [4]npmjs.com/package/bcryptjshttps://www.npmjs.com/package/bcryptjs
- [5]github.com/dcodeIO/bcrypt.jshttps://github.com/dcodeIO/bcrypt.js/issues/76
- [6]github.com/kelektiv/node.bcrypt.jshttps://github.com/kelektiv/node.bcrypt.js/issues/1037
- [7]github.com/dcodeIO/bcrypt.jshttps://github.com/dcodeIO/bcrypt.js/issues/58
- [8]github.com/dcodeIO/bcrypt.jshttps://github.com/dcodeIO/bcrypt.js#usage---async
- [9]github.com/dcodeIO/bcrypt.jshttps://github.com/dcodeIO/bcrypt.js/blob/master/index.js
- [10]raw.githubusercontent.com/dcodeIO/bcrypt.jshttps://raw.githubusercontent.com/dcodeIO/bcrypt.js/master/README.md
Need a different package?
Request a profile