CipherStash Docs

Troubleshooting

Common issues and fixes for @cipherstash/stack

Troubleshooting

Client initialization fails

Missing environment variables

The SDK reads CS_* environment variables by default. If any are missing, initialization fails with a ClientInitError.

ClientInitError: Missing workspace CRN

Fix: Set all required environment variables:

CS_WORKSPACE_CRN=crn:ap-southeast-2.aws:your-workspace-id
CS_CLIENT_ID=your-client-id
CS_CLIENT_KEY=your-client-key
CS_CLIENT_ACCESS_KEY=your-access-key

Or pass them explicitly in config:

explicit-config.ts
const client = await Encryption({
  schemas: [users],
  config: {
    workspaceCrn: "crn:ap-southeast-2.aws:your-workspace-id",
    clientId: "your-client-id",
    clientKey: "your-client-key",
    accessKey: "your-access-key",
  },
})

ZeroKMS connection timeout

If the SDK cannot reach ZeroKMS, initialization will time out.

Check:

  • Your application has outbound HTTPS access
  • No firewall or security group is blocking connections to *.viturhosted.net
  • The region in your CS_WORKSPACE_CRN matches your workspace's actual region

No schemas provided

The Encryption() function requires at least one schema:

schema-required.ts
// This will fail
const client = await Encryption({ schemas: [] })

// Provide at least one schema
const client = await Encryption({ schemas: [users] })

Decryption errors

Wrong keyset

If data was encrypted with keyset A but you're decrypting with keyset B, decryption will fail. Each keyset provides cryptographic isolation.

Fix: Ensure the client is configured with the same keyset that was used during encryption. Check the keyset option in your config or verify which keyset your client is associated with in the dashboard.

Lock context mismatch

If data was encrypted with identity-aware encryption, it can only be decrypted with the same user's identity.

DecryptionError: Lock context mismatch

Fix: Ensure you're using the same user's JWT for decryption that was used during encryption. The lock context binds encryption to the identity claims in the JWT.

Corrupted or tampered ciphertext

If the stored ciphertext has been modified, decryption will fail because AES-GCM-SIV provides authenticated encryption.

Fix: Check that no database triggers, application code, or migrations have modified the encrypted column values.

Search queries return no results

Missing EQL extension

Searchable encryption requires the EQL PostgreSQL extension. Without it, queries against encrypted columns won't work.

CREATE EXTENSION IF NOT EXISTS eql_v2;

Wrong query type

If you're searching with the wrong query type for your column's indexes, queries may return no results.

Check:

  • Using equality queries? The column needs .equality() in its schema.
  • Using freeTextSearch queries? The column needs .freeTextSearch() in its schema.
  • Using orderAndRange queries? The column needs .orderAndRange() in its schema.

Schema mismatch

The schema used to encrypt data must match the schema used to encrypt query terms. If you've changed your schema definition (added/removed indexes), existing encrypted data may not be searchable with the new schema.

Fix: Re-encrypt existing data with the updated schema if you've changed index configurations.

Native addon fails to load

Symptoms

Error: failed to load native addon
Error: module not found: @cipherstash/protect-ffi

Bundler not configured

@cipherstash/stack uses a native Node.js addon and cannot be processed by bundlers. You must exclude it.

Fix: See Bundling for configuration for Next.js, webpack, esbuild, and SST.

Linux deployment with npm lockfile v3

Some npm users see deployment failures on Linux (e.g., AWS Lambda) when their package-lock.json was created on macOS or Windows.

This happens with package-lock.json version 3, where npm only records native dependencies for the platform that created the lockfile. Linux builds can miss the native engine that @cipherstash/stack needs at runtime.

Who is affected:

  • You use npm ci in CI/CD
  • Your package-lock.json is version 3 and was generated on macOS or Windows
  • You deploy on Linux (Lambda, containers, EC2, etc.)

Fix: Use one of these solutions:

Option 1: Use pnpm (recommended)

pnpm install --frozen-lockfile

Option 2: Generate lockfile on Linux in CI

rm -f package-lock.json
npm install --package-lock-only --ignore-scripts --no-audit --no-fund --platform=linux --arch=x64
npm ci

Option 3: Pin lockfile to version 2

npm install --package-lock-only --lockfile-version=2

Quick verification

Before deploying, verify the native engine loads by running your app inside a Linux container or CI job.

Performance

Slow encrypt/decrypt operations

CipherStash encryption adds < 5ms overhead per operation. If you're seeing higher latency:

  1. Check network latency to ZeroKMS. Key derivation requires a round-trip to ZeroKMS. Deploy your application in the same AWS region as your workspace.
  2. Use bulk operations. bulkEncrypt and bulkDecrypt make a single ZeroKMS call regardless of record count, which is significantly faster for multiple values.
  3. Check your connection pool. If you're creating a new Encryption client per request, you're paying initialization cost each time. Initialize once and reuse the client.

Optimizing bulk operations

For best performance with bulk operations:

bulk-optimization.ts
// Slow: one ZeroKMS call per value
for (const user of users) {
  await client.encrypt(user.email, { column: schema.email, table: schema })
}

// Fast: one ZeroKMS call for all values
const plaintexts = users.map(u => ({ id: u.id, plaintext: u.email }))
await client.bulkEncrypt(plaintexts, { column: schema.email, table: schema })

Debugging

Enable debug logging to see detailed operation information:

STASH_STACK_LOG=debug

This logs key derivation requests, operation timing, and connection details. The SDK never logs plaintext data or key material at any log level.

On this page