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 CRNFix: 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-keyOr pass them explicitly in config:
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_CRNmatches your workspace's actual region
No schemas provided
The Encryption() function requires at least one schema:
// 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 mismatchFix: 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
equalityqueries? The column needs.equality()in its schema. - Using
freeTextSearchqueries? The column needs.freeTextSearch()in its schema. - Using
orderAndRangequeries? 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-ffiBundler 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 ciin CI/CD - Your
package-lock.jsonis 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-lockfileOption 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 ciOption 3: Pin lockfile to version 2
npm install --package-lock-only --lockfile-version=2Quick 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:
- Check network latency to ZeroKMS. Key derivation requires a round-trip to ZeroKMS. Deploy your application in the same AWS region as your workspace.
- Use bulk operations.
bulkEncryptandbulkDecryptmake a single ZeroKMS call regardless of record count, which is significantly faster for multiple values. - Check your connection pool. If you're creating a new
Encryptionclient per request, you're paying initialization cost each time. Initialize once and reuse the client.
Optimizing bulk operations
For best performance with bulk operations:
// 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=debugThis logs key derivation requests, operation timing, and connection details. The SDK never logs plaintext data or key material at any log level.