
mbc-debug
by mbc-net
serverless applications with CQRS on AWS, NestJS and local development
SKILL.md
name: mbc-debug description: Debug and troubleshoot MBC CQRS Serverless applications. Use this when encountering errors, investigating issues, or optimizing performance in MBC CQRS Serverless projects.
Pre-flight Check (Version Update)
Before executing this skill, check for updates:
- Run
mbc install-skills --checkto check if a newer version is available - If the output shows "Update available: X.Y.Z → A.B.C", ask the user:
- "A newer version of MBC skills is available (X.Y.Z → A.B.C). Would you like to update before proceeding?"
- If the user agrees, run
mbc install-skills --forceto update - If the user declines or skills are up-to-date, proceed with the skill
Note: Skip this check if the user explicitly says to skip updates or if you've already checked in this session.
MBC CQRS Serverless Debug Guide
This skill helps debug and troubleshoot issues in MBC CQRS Serverless applications.
Quick Error Lookup
Common Error Codes
| Error Code | Category | Quick Fix |
|---|---|---|
| MBC-CMD-001 | Command | Check pk/sk format |
| MBC-CMD-002 | Command | Verify version field |
| MBC-CMD-003 | Command | Check command type |
| MBC-DDB-001 | DynamoDB | Verify table exists |
| MBC-DDB-002 | DynamoDB | Check IAM permissions |
| MBC-DDB-003 | DynamoDB | Resolve version conflict |
| MBC-TNT-001 | Tenant | Verify tenantCode |
| MBC-TNT-002 | Tenant | Check tenant isolation |
| MBC-IMP-001 | Import | Validate CSV format |
| MBC-IMP-002 | Import | Check S3 permissions |
Debugging Workflows
1. Command Publishing Issues
Symptom: Command not being processed
Debug Steps:
// Step 1: Enable verbose logging
const logger = new Logger('CommandDebug');
// Step 2: Log the command before publishing
logger.debug('Publishing command:', JSON.stringify(command, null, 2));
// Step 3: Wrap in try-catch with detailed logging
try {
const result = await this.commandService.publishAsync(command, {
source: commandSource,
invokeContext,
});
logger.debug('Command result:', JSON.stringify(result, null, 2));
return result;
} catch (error) {
logger.error('Command failed:', {
error: error.message,
name: error.name,
command: { pk: command.pk, sk: command.sk, type: command.type },
});
throw error;
}
Common Causes:
- Missing required fields (pk, sk, type, version)
- Invalid pk/sk format
- Version mismatch (optimistic locking failure)
- DataSyncHandler not registered
2. ConditionalCheckFailedException
Symptom: Version conflict error
Debug Steps:
// Step 1: Check current version
const existing = await this.dataService.getItem({ pk, sk });
console.log('Current version:', existing.version);
// Step 2: Compare with command version
console.log('Command version:', command.version);
// Step 3: Investigate concurrent modifications
// Check CloudWatch logs for other requests modifying the same item
Solution:
// Always fetch the latest version before updating
async update(key: DetailKey, dto: UpdateDto, invokeContext: IInvoke) {
// Retry logic for version conflicts
const maxRetries = 3;
let retries = 0;
while (retries < maxRetries) {
try {
const existing = await this.dataService.getItem(key);
return await this.commandService.publishPartialUpdateAsync({
pk: key.pk,
sk: key.sk,
version: existing.version, // Always use latest version
...dto,
}, { source: commandSource, invokeContext });
} catch (error) {
if (error.name === 'ConditionalCheckFailedException') {
retries++;
if (retries >= maxRetries) {
throw new ConflictException('Too many concurrent modifications');
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 100 * retries));
continue;
}
throw error;
}
}
}
3. DataSyncHandler Not Triggering
Symptom: Data not syncing to RDS/Elasticsearch
Debug Checklist:
□ Handler is decorated with @DataSyncHandler({ type: 'ENTITY' })
□ Type matches the command's type field exactly
□ Handler is registered in module's dataSyncHandlers array
□ Handler implements IDataSyncHandler interface
□ up() method is async and properly awaited
Debug Steps:
// Step 1: Add logging to handler
@DataSyncHandler({ type: 'ORDER' })
export class OrderDataSyncRdsHandler implements IDataSyncHandler {
private readonly logger = new Logger(OrderDataSyncRdsHandler.name);
async up(cmd: CommandModel, data: DataModel): Promise<void> {
this.logger.log(`DataSync triggered for ${data.id}`);
this.logger.debug('Command:', JSON.stringify(cmd, null, 2));
this.logger.debug('Data:', JSON.stringify(data, null, 2));
// Your sync logic
}
}
// Step 2: Verify type matching
// In your command:
const command = new OrderCommandDto({
type: 'ORDER', // Must match @DataSyncHandler({ type: 'ORDER' })
});
// Step 3: Check module registration
CommandModule.register({
tableName: 'order',
dataSyncHandlers: [OrderDataSyncRdsHandler], // Must be included!
}),
4. Tenant Isolation Issues
Symptom: Cross-tenant data leakage or access denied
Debug Steps:
// Step 1: Log tenant context
const { tenantCode, userId } = getUserContext(invokeContext);
console.log('Tenant context:', { tenantCode, userId });
// Step 2: Verify PK includes tenant code
const pk = `ORDER#${tenantCode}`;
console.log('Generated PK:', pk);
// Step 3: Check data query includes tenant filter
const results = await this.dataService.listByPk({
pk: `ORDER#${tenantCode}`, // Tenant-scoped query
});
Common Causes:
- Missing tenantCode in pk
- Not calling getUserContext()
- Hardcoded pk without tenant scope
- Direct DynamoDB access bypassing tenant filter
5. Import Processing Issues
Symptom: Import job fails or gets stuck
Debug Checklist:
□ CSV file format is valid
□ S3 bucket permissions are correct
□ Step Functions execution has proper IAM role
□ Lambda timeout is sufficient
□ Memory allocation is adequate
Debug Steps:
// Step 1: Check Step Functions execution
// AWS Console → Step Functions → Executions → View details
// Step 2: Check Lambda logs
// AWS Console → CloudWatch → Log groups → /aws/lambda/import-handler
// Step 3: Validate CSV format locally
import * as csv from 'csv-parse';
const validateCsv = async (filePath: string) => {
const parser = fs.createReadStream(filePath).pipe(csv.parse({
columns: true,
skip_empty_lines: true,
}));
let rowCount = 0;
const errors: string[] = [];
for await (const row of parser) {
rowCount++;
// Validate required fields
if (!row.code) errors.push(`Row ${rowCount}: missing code`);
if (!row.name) errors.push(`Row ${rowCount}: missing name`);
}
return { rowCount, errors };
};
6. Performance Issues
Symptom: Slow API responses
Debug Areas:
DynamoDB Query Optimization
// Bad: Scanning entire table
const results = await this.dataService.scan(); // Avoid!
// Good: Query by partition key
const results = await this.dataService.listByPk({
pk: `ORDER#${tenantCode}`,
limit: 20,
});
// Better: Add GSI for common queries
// Check if GSI exists for your query pattern
N+1 Query Problem
// Bad: N+1 queries
const orders = await this.dataService.listByPk({ pk });
for (const order of orders) {
const customer = await this.customerService.findOne(order.customerId); // N queries!
}
// Good: Batch fetch
const orders = await this.dataService.listByPk({ pk });
const customerIds = [...new Set(orders.map(o => o.customerId))];
const customers = await this.customerService.findByIds(customerIds); // 1 query
const customerMap = new Map(customers.map(c => [c.id, c]));
Cold Start Optimization
// Enable provisioned concurrency for critical functions
// serverless.yml
functions:
api:
handler: dist/lambda.handler
provisionedConcurrency: 2
CloudWatch Log Queries
Find Errors by Request ID
fields @timestamp, @message
| filter @requestId = "REQUEST_ID_HERE"
| sort @timestamp asc
Find ConditionalCheckFailedException
fields @timestamp, @message
| filter @message like /ConditionalCheckFailedException/
| sort @timestamp desc
| limit 100
Find Slow Requests
fields @timestamp, @duration, @message
| filter @duration > 3000
| sort @duration desc
| limit 50
Find DataSyncHandler Executions
fields @timestamp, @message
| filter @message like /DataSync/
| sort @timestamp desc
| limit 100
Local Development Debugging
LocalStack Issues
Start LocalStack:
docker-compose up -d localstack
Verify Services:
# Check DynamoDB
aws --endpoint-url=http://localhost:4566 dynamodb list-tables
# Check S3
aws --endpoint-url=http://localhost:4566 s3 ls
# Check SQS
aws --endpoint-url=http://localhost:4566 sqs list-queues
Serverless Offline Debug
# Start with debug logging
DEBUG=* npm run offline
# Or enable specific debug namespaces
DEBUG=serverless:* npm run offline
VS Code Debug Configuration
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Serverless Offline",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "offline"],
"port": 9229,
"restart": true,
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
Diagnostic Commands
Check Package Versions
npm list @mbc-cqrs-serverless/core
npm list @mbc-cqrs-serverless/cli
Verify DynamoDB Table Schema
aws dynamodb describe-table --table-name YOUR_TABLE_NAME
Check Lambda Configuration
aws lambda get-function-configuration --function-name YOUR_FUNCTION_NAME
View Recent CloudWatch Logs
aws logs tail /aws/lambda/YOUR_FUNCTION_NAME --since 1h
Troubleshooting Decision Tree
Error Occurred
│
├── Is it a TypeScript compilation error?
│ └── Check import statements and type definitions
│
├── Is it a runtime error?
│ ├── ConditionalCheckFailedException?
│ │ └── Version mismatch - fetch latest version
│ │
│ ├── ResourceNotFoundException?
│ │ └── Table/Item doesn't exist - check table name
│ │
│ ├── ValidationError?
│ │ └── Check DTO validation decorators
│ │
│ └── Unknown error?
│ └── Check CloudWatch logs for stack trace
│
├── Is it a silent failure?
│ ├── DataSyncHandler not running?
│ │ └── Check type matching and registration
│ │
│ ├── Event not received?
│ │ └── Check SNS/SQS configuration
│ │
│ └── Command not processing?
│ └── Check Lambda invocation and DLQ
│
└── Is it a performance issue?
├── Cold start?
│ └── Enable provisioned concurrency
│
├── Slow queries?
│ └── Add GSI or optimize query pattern
│
└── Memory issues?
└── Increase Lambda memory allocation
Getting Help
When reporting issues, include:
- Error message and stack trace
- MBC CQRS Serverless version (
npm list @mbc-cqrs-serverless/core) - Node.js version (
node --version) - Relevant code snippets
- CloudWatch log excerpts
- Steps to reproduce
Resources:
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon


