Error Catalog
This catalog provides comprehensive documentation of errors encountered in MBC CQRS Serverless, including their causes, solutions, and recovery strategies.
Quick Reference
Use this table to quickly identify errors and jump to solutions.
Command & Data Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-CMD-001 | Invalid input: item not found or version mismatch | High | Fetch latest version or use version: -1 |
| MBC-CMD-002 | Invalid input key: item not found | Medium | Check if item exists before update |
| MBC-CMD-003 | Invalid input version | Medium | Use latest version from getItem() |
Tenant Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-TNT-001 | Tenant not found | High | Verify tenant exists with getTenant() |
| MBC-TNT-002 | Tenant already exists | Low | Check existence before creating |
Sequence & Task Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-SEQ-001 | Sequence not found | Medium | Sequence auto-initializes on first use |
| MBC-TSK-001 | Task not found | Medium | Verify task exists with NotFoundException |
Validation Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-VAL-001 | Validation failed | Medium | Check DTO constraints and input data |
DynamoDB Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-DDB-001 | ProvisionedThroughputExceededException | High | Implement exponential backoff retry |
| MBC-DDB-002 | ConditionalCheckFailedException | High | Refresh item and retry with new version |
| MBC-DDB-003 | ResourceNotFoundException | Critical | Verify table exists and check env vars |
| MBC-DDB-004 | ValidationException | Medium | Avoid empty strings, escape reserved words |
Authentication Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-COG-001 | NotAuthorizedException | High | Refresh token or re-authenticate |
| MBC-COG-002 | UserNotFoundException | Medium | Check user exists in pool |
| MBC-COG-003 | UserNotConfirmedException | Medium | Resend confirmation code |
Import Module Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-IMP-001 | Step Functions Timeout | Critical | Upgrade to v1.0.18+ for proper failure handling |
| MBC-IMP-002 | No import strategy found | High | Register ImportStrategy in module config |
| MBC-IMP-003 | Import stuck in PROCESSING | High | Check DynamoDB streams and SNS topics |
Step Functions Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-SFN-001 | TaskTimedOut | High | Increase Lambda timeout or chunk processing |
| MBC-SFN-002 | TaskFailed | High | Add proper error handling with sendTaskFailure |
AWS Service Errors
| Code | Error Message | Severity | Quick Fix |
|---|---|---|---|
| MBC-S3-001 | NoSuchKey | Medium | Check object exists with headObject |
| MBC-S3-002 | AccessDenied | High | Add required IAM permissions |
| MBC-SQS-001 | MessageNotInflight | Medium | Process within visibility timeout |
Command Service Errors
BadRequestException: "Invalid input: item not found or version mismatch"
Location: packages/core/src/commands/command.service.ts
Cause: Optimistic locking failure. The version number in the request does not match the current version in the database.
In versions prior to v1.0.25, this exception used the message "The input is not a valid, item not found or version not match". The wording was corrected in v1.0.25; the cause and solution are the same.
Solution:
// Option 1: Fetch latest version before update
const latest = await dataService.getItem({ pk, sk });
if (!latest) throw new NotFoundException('Item not found');
await commandService.publishPartialUpdateSync({
pk,
sk,
version: latest.version,
name: 'Updated Name',
}, options);
// Option 2: Use version: -1 for auto-fetch (async mode only)
await commandService.publishPartialUpdateAsync({
pk,
sk,
version: -1,
name: 'Updated Name',
}, options);
// Option 3: Implement retry logic
async function updateWithRetry(data, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const latest = await dataService.getItem({ pk: data.pk, sk: data.sk });
if (!latest) throw new NotFoundException('Item not found');
return await commandService.publishPartialUpdateSync({
...data,
version: latest.version,
}, options);
} catch (error) {
if (error.message.includes('version mismatch') && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, 100 * (i + 1)));
continue;
}
throw error;
}
}
}
BadRequestException: "Invalid input key: item not found"
Location: packages/core/src/commands/command.service.ts
Cause: Attempting to update an item that does not exist in the database.
Solution:
// Check if item exists first
const existing = await dataService.getItem({ pk, sk });
if (!existing) {
// Create new item
await commandService.publishAsync(newItem, options);
} else {
// Update existing item
await commandService.publishPartialUpdateAsync({
pk,
sk,
version: existing.version,
...updates,
}, options);
}
BadRequestException: "Invalid input version. The input version must be equal to the latest version"
Location: packages/core/src/commands/command.service.ts
Cause: Using a version in publishSync that does not match the latest saved version.
Solution: Fetch the latest item and use its version, or use version: -1 with async methods.
Tenant Errors
BadRequestException: "Tenant not found"
Location: packages/tenant/src/services/tenant.service.ts
Cause: The tenant code passed to addTenantGroup() or a similar mutation method does not exist. getTenant() does not throw this error — it returns undefined for missing tenants.
Solution:
// Verify tenant exists before mutating
const pk = `${TENANT_SYSTEM_PREFIX}${KEY_SEPARATOR}${SettingTypeEnum.TENANT}`;
const sk = `${TENANT_SK}${KEY_SEPARATOR}${tenantCode}`;
const tenant = await tenantService.getTenant({ pk, sk });
if (!tenant) {
console.log('Tenant does not exist:', tenantCode);
}
BadRequestException: "Tenant already exists"
Location: packages/tenant/src/services/tenant.service.ts
Cause: Attempting to create a tenant with an existing code.
Solution:
// Check if tenant exists before creating
const pk = `${TENANT_SYSTEM_PREFIX}${KEY_SEPARATOR}${SettingTypeEnum.TENANT}`;
const sk = `${TENANT_SK}${KEY_SEPARATOR}${tenantCode}`;
const existing = await tenantService.getTenant({ pk, sk });
if (existing && !existing.isDeleted) {
console.log('Tenant already exists, using existing tenant');
} else {
await tenantService.createTenant({ code: tenantCode, name: tenantName }, { invokeContext });
}
Sequence Errors
BadRequestException: "Sequence not found"
Location: packages/sequence/src/sequences.service.ts
Cause: The requested sequence key does not exist.
Solution:
// Generate sequence - auto-initializes on first use
try {
const result = await sequencesService.generateSequenceItem(
{
tenantCode,
typeCode: 'ORDER',
},
{ invokeContext },
);
} catch (error) {
// If error persists, check DynamoDB table permissions
}
Task Errors
NotFoundException: "Task not found"
Location: packages/task/src/task.controller.ts
Cause: The specified task does not exist or has been completed/deleted.
Solution:
// Verify task status before operations
const task = await taskService.getTask({ pk, sk });
if (!task) {
throw new NotFoundException('Task not found');
}
if (task.status === 'completed') {
throw new BadRequestException('Task already completed');
}
Validation Errors
BadRequestException: "Validation failed"
Location: packages/core/src/pipe/class.validation.pipe.ts
Cause: The request DTO failed class-validator validation.
Common Validation Errors:
// Example DTO with validation
export class CreateOrderDto {
@IsNotEmpty({ message: 'Name is required' })
@IsString()
@MaxLength(100)
name: string;
@IsNotEmpty({ message: 'Code is required' })
@Matches(/^[A-Z0-9-]+$/, { message: 'Code must be uppercase alphanumeric' })
code: string;
@IsOptional()
@IsNumber()
@Min(0)
amount?: number;
}
// Common validation errors and fixes:
// - "name must be a string" -> Ensure name is string type
// - "code should not be empty" -> Provide code value
// - "amount must not be less than 0" -> Use positive number
Solution:
// Validate before sending
import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
const dto = plainToInstance(CreateOrderDto, requestBody);
const errors = await validate(dto);
if (errors.length > 0) {
console.log('Validation errors:', errors.map(e => e.constraints));
}
DynamoDB Errors
ProvisionedThroughputExceededException
Location: AWS DynamoDB
Cause: Read or write capacity has been exceeded on on-demand or provisioned tables.
Solution:
// Implement exponential backoff retry
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 5,
baseDelay = 100
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.name === 'ProvisionedThroughputExceededException') {
const delay = baseDelay * Math.pow(2, i) + Math.random() * 100;
console.log(`Throughput exceeded, retrying in ${delay}ms...`);
await new Promise(r => setTimeout(r, delay));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
Prevention:
- Use on-demand capacity mode for unpredictable workloads
- Implement request batching to reduce write operations
- Use DAX for read-heavy workloads
ConditionalCheckFailedException
Location: AWS DynamoDB
Cause: Optimistic locking condition failed (version mismatch) or unique constraint violation.
Solution:
// Handle conditional check failure
try {
await commandService.publishSync(item, options);
} catch (error) {
if (error.name === 'ConditionalCheckFailedException') {
// Refresh and retry
const latest = await dataService.getItem({ pk, sk });
if (!latest) throw new NotFoundException('Item not found');
await commandService.publishSync({
...item,
version: latest.version,
}, options);
}
}
ResourceNotFoundException
Location: AWS DynamoDB
Cause: The specified table or index does not exist.
Solution:
# Verify table exists
aws dynamodb describe-table --table-name your-table-name
# Check environment variable
echo $DYNAMODB_TABLE_NAME
ValidationException: "One or more parameter values were invalid"
Location: AWS DynamoDB
Cause: Invalid key structure, empty string for non-key attribute, or reserved word conflict.
Solution:
// Avoid empty strings
const item = {
pk: 'ORDER#tenant001',
sk: 'ORDER#ORD001',
name: value || null, // Use null instead of empty string
};
// Use expression attribute names for reserved words
const params = {
ExpressionAttributeNames: {
'#name': 'name',
'#status': 'status',
},
};