Runtime Guides

Package-source copy · Generated into the site so runtime docs are searchable and linkable.

Troubleshooting (TypeScript)

This guide maps common problems to verified fixes for the TypeScript SDK.

Error: ENOENT: .../package.json when packaging

Cause: Running npm pack outside of ts/ (npm expects a package.json in the working directory).

Solution: Run packaging from inside ts/:

pushd ts
npm ci
npm run build
npm pack --pack-destination ../release-assets
popd

Error: CredentialsProviderError when using DynamoDB Local

Cause: AWS SDK v3 still requires credentials even for DynamoDB Local.

Solution: Provide dummy credentials:

const ddb = new DynamoDBClient({
  region: 'us-east-1',
  endpoint: 'http://localhost:8000',
  credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy' },
});

Error: Encrypted attribute used as a key

Cause: Encrypted attributes are not allowed for PK/SK or index keys.

Solution: Move secrets to non-key attributes and keep keys plaintext/stable.

Error: ErrTableNotFound or DynamoDB ResourceNotFoundException

Cause: the table name in defineModel({ table: { name } }) does not exist at the configured endpoint/region, or the client is pointed at AWS when you expected DynamoDB Local.

Fix: verify the model table name and endpoint, then create the table through your infrastructure or test setup.

const ddb = new DynamoDBClient({
  region: 'us-east-1',
  endpoint: process.env.DYNAMODB_ENDPOINT ?? 'http://localhost:8000',
  credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy' },
});

Error: ErrMissingPrimaryKey or empty key attributes

Cause: the item passed to create, get, update, or delete is missing the declared PK/SK attributes. DynamoDB keys cannot be empty strings.

Fix: construct keys in one place and keep the attribute names identical to the model schema.

const key = { PK: 'USER#42', SK: 'PROFILE' };
await db.get('User', key);

Error: GSI query returns no items or rejects consistent reads

Cause: querying a GSI requires .usingIndex(name), and DynamoDB does not support strongly consistent reads on GSIs.

Fix: specify the index and remove consistentRead(true) for GSI reads.

await db
  .query('User')
  .usingIndex('gsi_email')
  .partitionKey('EMAIL#a@example.com')
  .page();

Error: ErrEncryptionNotConfigured

Cause: a model contains encryption: { v: 1 }, but the TheorydbClient has no EncryptionProvider.

Fix: configure AwsKmsEncryptionProvider in production, or createDeterministicEncryptionProvider in tests. Do not remove the encryption marker to make a local test pass; encrypted fields fail closed by design.

Error: ErrEncryptedFieldNotQueryable

Cause: encrypted attributes cannot appear in key conditions, filters, or update conditions because DynamoDB cannot compare encrypted envelopes as plaintext.

Fix: query by stable plaintext keys (for example PK, SK, GSI1PK, GSI1SK) and store secrets in non-key encrypted attributes.

Pagination surprise: all() loads too much data

Cause: all() follows every cursor and materializes the full result set.

Fix: use page(), pages(), or items() for large partitions and stop iteration when the caller has enough data.

for await (const item of db
  .query('User')
  .partitionKey('TENANT#1')
  .limit(100)
  .items()) {
  if (done(item)) break;
}

Testing surprise: mock assertions are flaky around timestamps

Cause: lifecycle timestamps are generated at write time.

Fix: inject a deterministic clock with now and use the testkit fake for DynamoDB calls.

const db = new TheorydbClient(mock.client, {
  now: () => '2026-01-16T00:00:00.000000000Z',
}).register(User);