diff --git a/event.go b/event.go index 7538e66..8c9c523 100644 --- a/event.go +++ b/event.go @@ -466,7 +466,8 @@ func (e *Event) Err(err error) *Event { if e.stack && ErrorStackMarshaler != nil { switch m := ErrorStackMarshaler(err).(type) { case nil: - return e + // ErrorStackMarshaler returned nil — the error has no stack trace to + // attach. Fall through and still log the error via AnErr below. case LogObjectMarshaler: e = e.Object(ErrorStackFieldName, m) case error: diff --git a/event_test.go b/event_test.go index 1446947..08ed5ea 100644 --- a/event_test.go +++ b/event_test.go @@ -720,7 +720,13 @@ func TestEvent_ErrWithStackMarshalerNil(t *testing.T) { log.Log().Stack().Err(err).Msg("test message") got := buf.String() - want := `{"message":"test message"}` + "\n" // No fields because stack marshaler returned nil + // When ErrorStackMarshaler returns nil (no stack trace available for this + // error), Err() must still log the error value via AnErr. Without a stack + // field, the output is the same as if Stack() had not been called. + // Regression test for https://github.com/rs/zerolog/issues/762: + // commit f6fbd33 introduced a `case nil: return e` branch that silently + // swallowed the error instead of falling through to AnErr. + want := `{"error":"test error","message":"test message"}` + "\n" if got != want { t.Errorf("Event.Err() with nil stack marshaler = %q, want %q", got, want) }