Debugging and Troubleshooting Guide¶
This guide covers common issues you might encounter while developing LBS Foundry and how to resolve them.
Common Issues and Solutions¶
Build Issues¶
Compilation Errors¶
Symptoms: dotnet build fails with compilation errors
Solutions:
# 1. Clean and rebuild
dotnet clean LBS.slnx
dotnet build LBS.slnx
# 2. Restore dependencies
dotnet restore LBS.slnx
# 3. Check for missing dependencies
dotnet list package --outdated
Common Causes: - Missing NuGet packages - Version conflicts between packages - Syntax errors in recent changes - Missing using statements
Project Reference Issues¶
Symptoms: "Could not find project file" or assembly reference errors
Solutions:
# Verify project references
dotnet list LBS.slnx reference
# Re-add a problematic reference
dotnet remove reference path/to/project
dotnet add reference path/to/project
Database Issues¶
Connection Problems¶
Symptoms: "Cannot connect to database" or timeout errors
Diagnostics:
# Check PostgreSQL status
# Windows
net start postgresql
# macOS/Linux
brew services list | grep postgresql
systemctl status postgresql
# Test connection manually
psql -h localhost -U your_username -d lbs_foundry_dev
Solutions:
1. Check connection string in appsettings.json
2. Verify PostgreSQL is running
3. Check firewall settings
4. Validate credentials
Migration Issues¶
Symptoms: Database schema doesn't match expectations
Solutions:
# There is no separate migration step. Marten applies the schema automatically on
# application startup via ApplyAllDatabaseChangesOnStartup() (AutoCreate.All), so
# starting a host such as the API creates/updates the schema.
dotnet run --project src/Apps/LBS.Api/LBS.Api.csproj
# Reset database (development only), then start a host to re-apply the schema
dropdb lbs_foundry_dev
createdb lbs_foundry_dev
dotnet run --project src/Apps/LBS.Api/LBS.Api.csproj
Marten Projection Issues¶
Symptoms: Read models are empty or outdated
Diagnostics:
# Check projection status in database
SELECT name, lifecycle, last_seq_id FROM mt_event_progression;
Solutions:
# Schema objects are created automatically on host startup
# (ApplyAllDatabaseChangesOnStartup() / AutoCreate.All), and the async daemon
# (AddAsyncDaemon(DaemonMode.HotCold)) processes projections while a host runs.
dotnet run --project src/Apps/LBS.Api/LBS.Api.csproj
# To rebuild a projection, use Marten's projection rebuild API
# (IProjectionDaemon.RebuildProjectionAsync) from a host that has the event store
# configured, or drop and recreate the read-model schema and let it replay.
Frontend Issues¶
Node/pnpm Problems¶
Symptoms: Frontend won't start or has dependency issues
Solutions:
# Rebuild SDK (most common fix for foundry-web)
pnpm sdk:refresh
# Clear cache and reinstall (from repo root)
rm -rf node_modules sdk/typescript/node_modules src/Apps/foundry-web/node_modules
pnpm install
pnpm sdk:refresh
# Check Node version
node --version # Should be 18+
Build Failures¶
Symptoms: pnpm build fails
Common Issues: - TypeScript compilation errors - Missing environment variables - Linting failures
Solutions:
# Check TypeScript errors
pnpm tsc --noEmit
# Fix linting issues
pnpm lint --fix
# Check environment variables
cat .env.local
API Connection Issues¶
Symptoms: Frontend can't connect to backend API
Diagnostics: 1. Check backend is running: Visit http://localhost:5000/swagger 2. Verify API URLs in frontend configuration 3. Check CORS settings in backend 4. Inspect browser network tab for error details
Solutions:
# Check API base URL in frontend
grep -r "baseUrl" src/Apps/foundry-web/src/
# Verify backend CORS configuration
# Check src/Apps/LBS.Api/Program.cs
Authentication Issues¶
JWT Token Problems¶
Symptoms: "Unauthorized" errors despite being logged in
Diagnostics:
// Add logging to ClerkAuthenticationHandler
public async Task<AuthenticateResult> HandleAuthenticateAsync()
{
this.logger.LogDebug("Processing authentication request");
// ... existing logic
}
Solutions:
1. Check Clerk configuration in appsettings.json
2. Verify JWT token format in browser dev tools
3. Check token expiration
4. Validate Clerk public key
Service Account Authentication¶
Symptoms: Basic auth failing for service accounts
Diagnostics:
# Test basic auth manually
curl -H "Authorization: Basic $(echo -n 'email:password' | base64)" \
http://localhost:5000/api/readmodel
# Check user exists in database
psql -d lbs_foundry_dev -c "SELECT email, account_type FROM user_contracts WHERE email = 'service@example.com';"
Solutions: 1. Verify service account exists 2. Check password hash format 3. Validate basic auth header encoding
Event Sourcing Issues¶
Command Execution Failures¶
Symptoms: Commands throw exceptions or don't create events
Debugging Steps:
// Add detailed logging to aggregates
public void Execute(CreatePlayerCommand command)
{
this.logger.LogInformation("Executing CreatePlayerCommand for {PlayerId}", command.AggregateRootId);
try
{
// Validation logic
this.logger.LogDebug("Validation passed for {PlayerId}", command.AggregateRootId);
// Event creation
var @event = new PlayerCreatedEvent { /* ... */ };
this.RaiseEvent(@event);
this.logger.LogInformation("Successfully created PlayerCreatedEvent for {PlayerId}", command.AggregateRootId);
}
catch (Exception ex)
{
this.logger.LogError(ex, "Failed to execute CreatePlayerCommand for {PlayerId}", command.AggregateRootId);
throw;
}
}
Event Store Issues¶
Symptoms: Events not being persisted or loaded correctly
Diagnostics:
-- Check event storage
SELECT stream_id, type, data, timestamp
FROM mt_events
WHERE stream_id = 'player-12345'
ORDER BY version;
-- Check for event processing errors
SELECT * FROM mt_event_progression WHERE last_exception IS NOT NULL;
Projection Failures¶
Symptoms: Read models not updating after commands
Debugging:
// Add logging to projection builders
public void Apply(PlayerCreatedEvent @event, PlayerContract contract)
{
this.logger.LogDebug("Applying PlayerCreatedEvent {EventId} to contract {ContractId}",
@event.Id, contract.Id);
contract.Id = @event.AggregateRootId.Value;
contract.PlayerName = @event.PlayerName;
// ... other properties
this.logger.LogDebug("Successfully applied PlayerCreatedEvent to contract {ContractId}", contract.Id);
}
Authorization Issues¶
Role-Based Access Problems¶
Symptoms: "Access denied" errors for valid users
Debugging:
// Add authorization logging
[RequiresRoles(RoleDefinition.Member)]
public class MyCommand : DomainCommand<MyId>, IRequiresUserContext
{
public ClaimsPrincipal? User => UserContext.Current;
}
// In SecurityCommandExecutor
public async Task<IReadOnlyList<IDomainEvent>> ExecuteAsync<TId>(IDomainCommand<TId> command, int expectedVersion)
{
this.logger.LogDebug("Checking authorization for command {CommandType}", command.GetType().Name);
var requiredRoles = this.securityMapping.GetRequiredRoles(command.GetType());
this.logger.LogDebug("Required roles: {Roles}", string.Join(", ", requiredRoles ?? Array.Empty<string>()));
var user = UserContext.Current;
var userRoles = user?.FindAll(ClaimTypes.Role).Select(c => c.Value).ToArray() ?? Array.Empty<string>();
this.logger.LogDebug("User roles: {UserRoles}", string.Join(", ", userRoles));
// ... authorization logic
}
Security Mapping Issues¶
Symptoms: Authorization attributes not being detected
Solutions: 1. Verify attribute placement on command/query classes 2. Check assembly scanning in startup 3. Validate role definitions match exactly 4. Ensure ISecurityMapping is registered in DI
Testing Issues¶
Test Database Problems¶
Symptoms: Tests failing due to database state
Solutions:
// Use proper test isolation
[SetUp]
public async Task SetUp()
{
// Create test database session
this.session = this.store.LightweightSession();
// Clear any existing data
await this.session.DeleteWhere<PlayerContract>(x => true);
await this.session.SaveChangesAsync();
}
[TearDown]
public void TearDown()
{
this.session?.Dispose();
}
Authorization Test Failures¶
Symptoms: Authorization tests not working correctly
Solutions:
// Use proper test helpers
[Test]
public async Task MyCommand_WithValidRole_ShouldSucceed()
{
// Use the authorization test helper
using (AuthorizationTestHelpers.SetTestUser(RoleDefinition.Member))
{
var command = new MyCommand { /* ... */ };
var events = await this.commandExecutor.ExecuteAsync(command, 0);
events.Should().HaveCount(1);
}
}
Performance Issues¶
Slow Query Performance¶
Symptoms: Queries taking too long to execute
Diagnostics:
-- Check query execution plans
EXPLAIN ANALYZE SELECT * FROM player_contracts WHERE team_id = 'team-123';
-- Check missing indexes
SELECT schemaname, tablename, attname, n_distinct, correlation
FROM pg_stats
WHERE tablename = 'player_contracts';
Solutions: 1. Add appropriate indexes to read model contracts 2. Optimize query filters and ordering 3. Consider pagination for large result sets 4. Use appropriate session types (lightweight vs identity)
Memory Issues¶
Symptoms: High memory usage or OutOfMemoryException
Solutions:
// Use proper session disposal
public async Task<IEnumerable<PlayerContract>> GetPlayersAsync()
{
using var session = this.store.LightweightSession();
return await session.Query<PlayerContract>().ToListAsync();
}
// Avoid loading large aggregates
// Use snapshots for aggregates with many events
public class PlayerAggregateWithSnapshot : PlayerAggregate, ISnapshot
{
// Implement snapshot functionality
}
Development Tools¶
Aspire Dashboard¶
Access: http://localhost:15000
Use for: - Monitoring service health - Viewing application logs - Checking HTTP requests/responses - Database connection monitoring
Database Administration¶
# Connect to development database
psql -h localhost -U lbs_dev lbs_foundry_dev
# Useful queries
-- Check event streams
SELECT DISTINCT stream_id FROM mt_events LIMIT 10;
-- Check projections
SELECT name, lifecycle, last_seq_id FROM mt_event_progression;
-- Check read models
SELECT count(*) FROM player_contracts;
API Testing¶
Swagger UI: http://localhost:5000/swagger
Postman Collection:
{
"info": { "name": "LBS Foundry API" },
"item": [
{
"name": "Query Players",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/readmodel",
"body": {
"mode": "raw",
"raw": "{\n \"query\": {\n \"queryType\": \"PlayerSearch\",\n \"searchTerm\": \"smith\"\n },\n \"dataType\": \"PlayerContract\"\n}"
}
}
}
]
}
Monitoring and Observability¶
Application Logging¶
Configuration (appsettings.json):
{
"Logging": {
"LogLevel": {
"Default": "Information",
"LBS": "Debug",
"Microsoft.AspNetCore": "Warning"
}
}
}
Structured Logging:
this.logger.LogInformation("Player created with ID {PlayerId} and name {PlayerName}",
playerId, playerName);
this.logger.LogError(exception, "Failed to process command {CommandType} for aggregate {AggregateId}",
command.GetType().Name, command.AggregateRootId);
Performance Monitoring¶
// Add timing to critical operations
public async Task<IReadOnlyList<IDomainEvent>> ExecuteAsync<TId>(IDomainCommand<TId> command, int expectedVersion)
{
using var activity = this.activitySource.StartActivity("CommandExecution");
activity?.SetTag("command.type", command.GetType().Name);
activity?.SetTag("aggregate.id", command.AggregateRootId.ToString());
var stopwatch = Stopwatch.StartNew();
try
{
var result = await this.innerExecutor.ExecuteAsync(command, expectedVersion);
activity?.SetTag("events.count", result.Count);
this.logger.LogInformation("Command {CommandType} executed in {ElapsedMs}ms",
command.GetType().Name, stopwatch.ElapsedMilliseconds);
return result;
}
catch (Exception ex)
{
activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
throw;
}
}
When All Else Fails¶
Nuclear Options (Development Only)¶
# Complete reset - use with caution!
# 1. Reset git state
git clean -fdx
git reset --hard HEAD
# 2. Reset database
dropdb lbs_foundry_dev
createdb lbs_foundry_dev
# 3. Clear all caches
dotnet nuget locals all --clear
rm -rf node_modules sdk/typescript/node_modules src/Apps/foundry-web/node_modules
# 4. Fresh setup (Marten applies the schema on host startup — no migration step)
dotnet restore LBS.slnx
dotnet build LBS.slnx
pnpm install
pnpm sdk:refresh
dotnet run --project src/Apps/LBS.Api/LBS.Api.csproj
Getting Help¶
- Check logs in Aspire dashboard first
- Search this troubleshooting guide for similar issues
- Ask in development channel with:
- Error message/symptoms
- Steps to reproduce
- What you've already tried
- Relevant log output
- Create an issue for reproducible bugs
Still stuck? The development team is here to help! Don't hesitate to ask questions.