How It Works Features Pricing Blog Error Guides
Log In Start Free Trial
Node.js · JavaScript

Fix Error: error:1C80006B:Provider routines::wrong final block length in Node.js

This error occurs when decrypting data with an incorrect key, wrong IV, or corrupted ciphertext, causing the padding validation to fail. The cipher expects specific block alignment that does not match the input. Fix it by ensuring the encryption key, IV, and algorithm match between encryption and decryption.

Reading the Stack Trace

Error: error:1C80006B:Provider routines::wrong final block length at Decipheriv.final (node:internal/crypto/cipher:193:29) at decrypt (src/utils/encryption.js:24:28) at TokenService.verify (src/services/tokenService.js:18:22) at authMiddleware (src/middleware/auth.js:12:30) at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5) at trim_prefix (node_modules/express/lib/router/index.js:328:13) at /node_modules/express/lib/router/index.js:286:9 at Function.process_params (node_modules/express/lib/router/index.js:346:12) at next (node_modules/express/lib/router/index.js:280:10) at expressInit (node_modules/express/lib/middleware/init.js:40:5)

Here's what each line means:

Common Causes

1. Encryption key changed between encrypt and decrypt

The secret key used for encryption differs from the one used for decryption, causing padding validation to fail.

const crypto = require('crypto');
const key = process.env.ENCRYPTION_KEY; // Changed after tokens were issued
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
decipher.update(encrypted);
decipher.final(); // Fails: wrong key

2. IV not stored or transmitted with ciphertext

The initialization vector used for encryption is not saved alongside the ciphertext, so decryption uses a wrong or default IV.

function encrypt(text) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
  return cipher.update(text) + cipher.final(); // IV is lost
}

3. Encoding mismatch between encrypt and decrypt

The ciphertext is encoded as hex during encryption but decoded as base64 during decryption, corrupting the data.

// Encryption: outputs hex
const encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex');
// Decryption: expects base64
decipher.update(encrypted, 'base64', 'utf8'); // Wrong encoding

The Fix

Generate a random IV for each encryption and prepend it to the ciphertext. On decryption, extract the IV from the payload before decrypting. Use consistent Buffer encoding throughout to avoid corruption. Validate the payload format before attempting decryption.

Before (broken)
const crypto = require('crypto');

function encrypt(text, key) {
  const cipher = crypto.createCipheriv('aes-256-cbc', key, Buffer.alloc(16));
  return cipher.update(text, 'utf8', 'hex') + cipher.final('hex');
}

function decrypt(encrypted, key) {
  const decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.alloc(16));
  return decipher.update(encrypted, 'hex', 'utf8') + decipher.final('utf8');
}
After (fixed)
const crypto = require('crypto');

const ALGORITHM = 'aes-256-cbc';
const IV_LENGTH = 16;

function encrypt(text, key) {
  const iv = crypto.randomBytes(IV_LENGTH);
  const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(key, 'hex'), iv);
  const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
  return iv.toString('hex') + ':' + encrypted.toString('hex');
}

function decrypt(payload, key) {
  const [ivHex, encryptedHex] = payload.split(':');
  if (!ivHex || !encryptedHex) {
    throw new Error('Invalid encrypted payload format');
  }
  const iv = Buffer.from(ivHex, 'hex');
  const encrypted = Buffer.from(encryptedHex, 'hex');
  const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(key, 'hex'), iv);
  return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
}

Testing the Fix

const { encrypt, decrypt } = require('./encryption');
const crypto = require('crypto');

const key = crypto.randomBytes(32).toString('hex');

describe('Encryption', () => {
  it('encrypts and decrypts a string successfully', () => {
    const text = 'hello world';
    const encrypted = encrypt(text, key);
    const decrypted = decrypt(encrypted, key);
    expect(decrypted).toBe(text);
  });

  it('produces different ciphertext for same input (random IV)', () => {
    const text = 'test';
    const a = encrypt(text, key);
    const b = encrypt(text, key);
    expect(a).not.toBe(b);
  });

  it('throws on invalid payload format', () => {
    expect(() => decrypt('invalidpayload', key)).toThrow('Invalid encrypted payload format');
  });

  it('throws when decrypting with wrong key', () => {
    const encrypted = encrypt('secret', key);
    const wrongKey = crypto.randomBytes(32).toString('hex');
    expect(() => decrypt(encrypted, wrongKey)).toThrow();
  });
});

Run your tests:

npm test

Pushing Through CI/CD

git checkout -b fix/nodejs-crypto-error,git add src/utils/encryption.js src/utils/__tests__/encryption.test.js,git commit -m "fix: use random IV and consistent encoding for crypto operations",git push origin fix/nodejs-crypto-error

Your CI config should look something like this:

name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm test -- --coverage
      - run: npm run lint

The Full Manual Process: 18 Steps

Here's every step you just went through to fix this one bug:

  1. Notice the error alert or see it in your monitoring tool
  2. Open the error dashboard and read the stack trace
  3. Identify the file and line number from the stack trace
  4. Open your IDE and navigate to the file
  5. Read the surrounding code to understand context
  6. Reproduce the error locally
  7. Identify the root cause
  8. Write the fix
  9. Run the test suite locally
  10. Fix any failing tests
  11. Write new tests covering the edge case
  12. Run the full test suite again
  13. Create a new git branch
  14. Commit and push your changes
  15. Open a pull request
  16. Wait for code review
  17. Merge and deploy to production
  18. Monitor production to confirm the error is resolved

Total time: 30-60 minutes. For one bug.

Or Let bugstack Fix It in Under 2 minutes

Every step above? bugstack does it automatically.

Step 1: Install the SDK

npm install bugstack-sdk

Step 2: Initialize

const { initBugStack } = require('bugstack-sdk')

initBugStack({ apiKey: process.env.BUGSTACK_API_KEY })

Step 3: There is no step 3.

bugstack handles everything from here:

  1. Captures the stack trace and request context
  2. Pulls the relevant source files from your GitHub repo
  3. Analyzes the error and understands the code context
  4. Generates a minimal, verified fix
  5. Runs your existing test suite
  6. Pushes through your CI/CD pipeline
  7. Deploys to production (or opens a PR for review)

Time from error to fix deployed: Under 2 minutes.

Human involvement: zero.

Try bugstack Free →

No credit card. 5-minute setup. Cancel anytime.

Deploying the Fix (Manual Path)

  1. Update encryption functions to use random IVs prepended to ciphertext.
  2. Ensure consistent encoding (hex or base64) between encrypt and decrypt.
  3. Run tests to verify round-trip encryption/decryption.
  4. Plan a migration for existing encrypted data if key format changed.
  5. Open a PR, merge after CI, and verify in staging.

Frequently Asked Questions

BugStack runs the fix through your existing test suite, generates additional edge-case tests, and validates that no other modules are affected before marking it safe to deploy.

BugStack never pushes directly to production. Every fix goes through a pull request with full CI checks, so your team can review it before merging.

Decrypt existing data with the old method, then re-encrypt with the new method. Do this in a migration script, not at runtime, and run it before deploying the new code.

AES-256-GCM is preferred because it provides authenticated encryption, detecting tampering. CBC mode requires a separate HMAC to verify integrity, adding complexity.