However, Database.DB() returns the GORM *gorm.DB which is only set during the database's OnStart lifecycle hook (in connect()). The engine's constructor runs during fx dependency resolution, which happens before any OnStart hooks fire. Therefore params.DB.DB() returns nil.
When the delivery engine's background goroutine first polls (after pollInterval = 2 seconds), it calls e.db.Where(...) on a nil pointer, causing the panic.
Store params.DB (the *database.Database wrapper) instead of params.DB.DB(), and call .DB() lazily in processPending() or in the OnStart hook:
typeEnginestruct{database*database.Database// Store the wrapper...}func(e*Engine)processPending(ctxcontext.Context){db:=e.database.DB()// Get the connection lazily...}
Alternatively, move the db assignment into the engine's OnStart hook, which runs after the database's OnStart.
Reproduction
exportDBURL="file:test.db?cache=shared&mode=rwc"exportWEBHOOKER_ENVIRONMENT=dev
exportSESSION_KEY="<valid-32-byte-base64-key>"
./bin/webhooker
# Crashes after ~2 seconds
Impact
The application is unusable. It crashes on every startup before any webhook can be received or delivered. This blocks the 1.0 release.
## Bug
The delivery engine crashes with a nil pointer dereference approximately 2 seconds after application startup.
## Root Cause
In `internal/delivery/engine.go`, the `New()` constructor stores `params.DB.DB()` at construction time:
```go
func New(lc fx.Lifecycle, params EngineParams) *Engine {
e := &Engine{
db: params.DB.DB(), // Returns nil here!
...
}
```
However, `Database.DB()` returns the GORM `*gorm.DB` which is only set during the database's `OnStart` lifecycle hook (in `connect()`). The engine's constructor runs during fx dependency resolution, which happens *before* any `OnStart` hooks fire. Therefore `params.DB.DB()` returns `nil`.
When the delivery engine's background goroutine first polls (after `pollInterval` = 2 seconds), it calls `e.db.Where(...)` on a nil pointer, causing the panic.
## Stack Trace
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x28]
goroutine 132 [running]:
gorm.io/gorm.(*DB).getInstance(0x0?)
gorm.go:399 +0x18
gorm.io/gorm.(*DB).Where(...)
chainable_api.go:201 +0x30
sneak.berlin/go/webhooker/internal/delivery.(*Engine).processPending(...)
engine.go:114 +0xd0
sneak.berlin/go/webhooker/internal/delivery.(*Engine).run(...)
engine.go:106 +0x94
```
## Fix
Store `params.DB` (the `*database.Database` wrapper) instead of `params.DB.DB()`, and call `.DB()` lazily in `processPending()` or in the `OnStart` hook:
```go
type Engine struct {
database *database.Database // Store the wrapper
...
}
func (e *Engine) processPending(ctx context.Context) {
db := e.database.DB() // Get the connection lazily
...
}
```
Alternatively, move the `db` assignment into the engine's `OnStart` hook, which runs after the database's `OnStart`.
## Reproduction
```bash
export DBURL="file:test.db?cache=shared&mode=rwc"
export WEBHOOKER_ENVIRONMENT=dev
export SESSION_KEY="<valid-32-byte-base64-key>"
./bin/webhooker
# Crashes after ~2 seconds
```
## Impact
The application is unusable. It crashes on every startup before any webhook can be received or delivered. This blocks the 1.0 release.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Bug
The delivery engine crashes with a nil pointer dereference approximately 2 seconds after application startup.
Root Cause
In
internal/delivery/engine.go, theNew()constructor storesparams.DB.DB()at construction time:However,
Database.DB()returns the GORM*gorm.DBwhich is only set during the database'sOnStartlifecycle hook (inconnect()). The engine's constructor runs during fx dependency resolution, which happens before anyOnStarthooks fire. Thereforeparams.DB.DB()returnsnil.When the delivery engine's background goroutine first polls (after
pollInterval= 2 seconds), it callse.db.Where(...)on a nil pointer, causing the panic.Stack Trace
Fix
Store
params.DB(the*database.Databasewrapper) instead ofparams.DB.DB(), and call.DB()lazily inprocessPending()or in theOnStarthook:Alternatively, move the
dbassignment into the engine'sOnStarthook, which runs after the database'sOnStart.Reproduction
Impact
The application is unusable. It crashes on every startup before any webhook can be received or delivered. This blocks the 1.0 release.