diff --git a/internal/app/media.go b/internal/app/media.go index 6417aaf..5df8ad2 100644 --- a/internal/app/media.go +++ b/internal/app/media.go @@ -87,6 +87,13 @@ func (a *App) runMediaWorkers(ctx context.Context, jobs <-chan mediaJob, workers wg.Add(1) go func() { defer wg.Done() + // Recover from panics to prevent a bad media job from crashing + // the whole process (#52). + defer func() { + if r := recover(); r != nil { + fmt.Fprintf(os.Stderr, "media worker panic (recovered): %v\n", r) + } + }() for { select { case <-ctx.Done(): diff --git a/internal/app/sync.go b/internal/app/sync.go index e1e8bdc..01e2942 100644 --- a/internal/app/sync.go +++ b/internal/app/sync.go @@ -80,6 +80,13 @@ func (a *App) Sync(ctx context.Context, opts SyncOptions) (SyncResult, error) { } handlerID := a.wa.AddEventHandler(func(evt interface{}) { + // Recover from panics so unexpected message structures do not + // crash the entire process (#52). + defer func() { + if r := recover(); r != nil { + fmt.Fprintf(os.Stderr, "\nevent handler panic (recovered): %v\n", r) + } + }() lastEvent.Store(time.Now().UTC().UnixNano()) switch v := evt.(type) {