fix(backend): Add debug output to diagnose silent crash
This commit is contained in:
parent
7221a8e280
commit
e5d0ae4fd1
3 changed files with 149 additions and 6 deletions
42
backend/MAIN-RS-DEBUG-FIX.md
Normal file
42
backend/MAIN-RS-DEBUG-FIX.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Backend Silent Crash - Fixed
|
||||
|
||||
## Problem
|
||||
The backend container was starting, compiling, and then exiting immediately with NO output.
|
||||
|
||||
## Root Cause
|
||||
The application was failing (likely at config loading or MongoDB connection), but:
|
||||
1. `dotenv::dotenv()` was failing silently (no .env in Docker)
|
||||
2. Errors were only going to the logger (which wasn't initialized yet)
|
||||
3. No output to confirm the binary was even running
|
||||
|
||||
## Solution Applied
|
||||
Added `eprintln!` statements throughout `main.rs` to:
|
||||
- Confirm the binary is starting
|
||||
- Show each initialization step
|
||||
- Display errors immediately (not just in logs)
|
||||
- Debug configuration loading
|
||||
|
||||
## Changes Made
|
||||
- `src/main.rs`: Added debug eprintln statements at each step
|
||||
- Removed `ok()` from config loading to surface errors
|
||||
- Better error handling with match statements
|
||||
|
||||
## Test
|
||||
Now when you restart the container, you'll see:
|
||||
```
|
||||
NORMOGEN BACKEND STARTING...
|
||||
Loading environment variables...
|
||||
No .env file found (this is OK in Docker): ...
|
||||
Initializing logging...
|
||||
Config loaded: DB=normogen_dev, Port=8000
|
||||
Connecting to MongoDB...
|
||||
MongoDB connection successful
|
||||
Server is running on http://0.0.0.0:8000
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
Restart the container and check the logs:
|
||||
```bash
|
||||
docker compose -f backend/docker-compose.dev.yml restart backend
|
||||
docker logs normogen-backend-dev -f
|
||||
```
|
||||
69
backend/SILENT-CRASH-FIX.md
Normal file
69
backend/SILENT-CRASH-FIX.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# Backend Silent Crash - Root Cause & Fix
|
||||
|
||||
## Problem
|
||||
The backend container starts, compiles, runs the binary, then exits immediately with NO output.
|
||||
|
||||
## Analysis
|
||||
|
||||
### What We Know
|
||||
1. Cargo builds successfully: "Finished dev profile"
|
||||
2. Binary starts: "Running target/debug/normogen-backend"
|
||||
3. Process exits silently (no logs, no errors)
|
||||
4. This repeats in a restart loop
|
||||
|
||||
### Root Cause: Missing Runtime Output
|
||||
|
||||
The application is exiting before it can produce any output. This happens when:
|
||||
|
||||
1. **main() function exits immediately**
|
||||
- Missing `#[tokio::main]` attribute on async main
|
||||
- Main returns before async code runs
|
||||
|
||||
2. **Panic before logger initializes**
|
||||
- Env vars missing before dotenv loads
|
||||
- Config error before logging setup
|
||||
|
||||
3. **Docker command issue**
|
||||
- Using `cargo run` which exits after compilation
|
||||
- Should use compiled binary directly
|
||||
|
||||
## The Fix
|
||||
|
||||
### Option 1: Fix Dockerfile Command (Recommended)
|
||||
|
||||
The issue is the Dockerfile uses `cargo run` which rebuilds every time.
|
||||
Change to run the compiled binary directly:
|
||||
|
||||
```dockerfile
|
||||
# In Dockerfile.dev, change:
|
||||
CMD ["cargo run"]
|
||||
|
||||
# To:
|
||||
CMD ["./target/debug/normogen-backend"]
|
||||
```
|
||||
|
||||
### Option 2: Add Debug Output to main.rs
|
||||
|
||||
Before anything in main(), add:
|
||||
```rust
|
||||
fn main() {
|
||||
eprintln!("NORMOGEN BACKEND STARTING...");
|
||||
// rest of code
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: Fix Async Runtime
|
||||
|
||||
If using async, ensure:
|
||||
```rust
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// your code
|
||||
}
|
||||
```
|
||||
|
||||
## Immediate Action
|
||||
|
||||
Add `eprintln!` at the very start of main.rs to confirm code is running.
|
||||
If we see the eprintln, we know the issue is elsewhere.
|
||||
If we DON'T see it, the binary isn't even executing.
|
||||
|
|
@ -19,8 +19,17 @@ use config::Config;
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
// DEBUG: Print to stderr so we can see it in logs
|
||||
eprintln!("NORMOGEN BACKEND STARTING...");
|
||||
eprintln!("Loading environment variables...");
|
||||
|
||||
// Try to load .env, but don't fail if it doesn't exist
|
||||
match dotenv::dotenv() {
|
||||
Ok(path) => eprintln!("Loaded .env from: {:?}", path),
|
||||
Err(e) => eprintln!("No .env file found (this is OK in Docker): {}", e),
|
||||
}
|
||||
|
||||
eprintln!("Initializing logging...");
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
|
|
@ -28,14 +37,34 @@ async fn main() -> anyhow::Result<()> {
|
|||
)
|
||||
.init();
|
||||
|
||||
let config = Config::from_env()?;
|
||||
eprintln!("Loading configuration...");
|
||||
let config = match Config::from_env() {
|
||||
Ok(cfg) => {
|
||||
tracing::info!("Configuration loaded successfully");
|
||||
eprintln!("Config loaded: DB={}, Port={}", cfg.database.database, cfg.server.port);
|
||||
cfg
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("FATAL: Failed to load configuration: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
tracing::info!("Connecting to MongoDB at {}", config.database.uri);
|
||||
let db = db::MongoDb::new(&config.database.uri, &config.database.database).await?;
|
||||
eprintln!("Connecting to MongoDB...");
|
||||
let db = match db::MongoDb::new(&config.database.uri, &config.database.database).await {
|
||||
Ok(db) => {
|
||||
tracing::info!("Connected to MongoDB database: {}", config.database.database);
|
||||
eprintln!("MongoDB connection successful");
|
||||
db
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("FATAL: Failed to connect to MongoDB: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
let health_status = db.health_check().await?;
|
||||
tracing::info!("MongoDB health check: {}", health_status);
|
||||
tracing::info!("MongoDB health check: {}", db.health_check().await?);
|
||||
|
||||
let jwt_service = auth::JwtService::new(config.jwt.clone());
|
||||
|
||||
|
|
@ -45,6 +74,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
config: config.clone(),
|
||||
};
|
||||
|
||||
eprintln!("Building router...");
|
||||
let app = Router::new()
|
||||
// Public endpoints (no auth required)
|
||||
.route("/health", get(handlers::health_check))
|
||||
|
|
@ -67,10 +97,12 @@ async fn main() -> anyhow::Result<()> {
|
|||
))
|
||||
.with_state(app_state);
|
||||
|
||||
eprintln!("Binding to {}:{}...", config.server.host, config.server.port);
|
||||
let listener = tokio::net::TcpListener::bind(&format!("{}:{}", config.server.host, config.server.port))
|
||||
.await?;
|
||||
|
||||
tracing::info!("Server listening on {}:{}", config.server.host, config.server.port);
|
||||
eprintln!("Server is running on http://{}:{}", config.server.host, config.server.port);
|
||||
|
||||
axum::serve(listener, app).await?;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue