BLOCKER: Delivery engine crashes with nil pointer dereference on startup #17

Closed
opened 2026-03-02 01:27:43 +01:00 by clawbot · 0 comments
Collaborator

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:

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:

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

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.

## 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.
clawbot added the
bot
label 2026-03-02 01:27:43 +01:00
sneak closed this issue 2026-03-04 01:19:43 +01:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/webhooker#17
No description provided.