fix: record error field when ErrorStackMarshaler returns nil#758
fix: record error field when ErrorStackMarshaler returns nil#758walsm232 wants to merge 1 commit into
Conversation
A nil return from ErrorStackMarshaler means no stack trace is available, not that the error itself should be omitted. Restore pre-v1.35 behavior where Err() continues to call AnErr() so the error field is always recorded. Fixes a regression introduced in rs#748. Signed-off-by: Michael Walsh <michael.walsh@elastic.co>
There was a problem hiding this comment.
Pull request overview
This PR restores the pre-v1.35 behavior where a nil return from ErrorStackMarshaler(err) suppresses only the stack field (e.g. "stack") but does not suppress the primary error field (e.g. "error"), fixing a regression introduced by the early-return logic added in #748.
Changes:
- Stop early-returning from
Event.Err()andContext.Err()whenErrorStackMarshalerreturnsnil, soAnErr(ErrorFieldName, err)still runs. - Stop early-returning from
appendFieldList’s error+stack path whenErrorStackMarshalerreturnsnil, so field processing continues normally. - Update tests to assert that the error field is still emitted when the stack marshaler returns
nil.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
fields.go |
Removes early return on ErrorStackMarshaler(...) == nil so subsequent fields aren’t skipped and stack omission doesn’t alter other output. |
event.go |
Ensures Err(err) still records the main error field even when no stack trace is available. |
event_test.go |
Updates expectation to include the error field for the nil-stack-marshaler case. |
context.go |
Ensures Context.Err(err) still records the main error field even when no stack trace is available. |
context_test.go |
Updates expectation to include the error field for the nil-stack-marshaler case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
cc: @IDisposable in case you get an opportunity to look as I think you made the related changes |
|
Dropping the error field was definitely an oversight. Sorry for introducing this bug. Your fix look perfect. If it affected the coverage, it's legitimately because of a limitation of the testing tool. |
Note
I am not certain that this is a bug but it does look like one - at least the behaviour has changed in a way that I am not sure is expected / intended but I'm hoping you folks might be able to help confirm / take a look
In
v1.35,Event.Err/Context.Err(and the stack path inappendFieldListfor error values) return early whenErrorStackMarshaler(err)returnsnil. That skips the subsequentAnErr/ field encoding, so the main error field is omitted from the log line.A
nilreturn fromErrorStackMarshalermeans “nothing to put in the stack field” (e.g. plainerrors.New/fmt.Errorfwithout a pkg/errors-style stack). I don't think it should mean “omit the error entirely”This regressed from
v1.34, where an empty casenilbranch still fell through toAnErr.The behavior change was introduced in #748 (commit f6fbd33).
How to Reproduce
Minimal setup: enable stack on the logger (
With().Stack()orlog.Log().Stack()), set a globalErrorStackMarshalerthat returnsnil(same idea asgo.elastic.co/ecszerolog/internal.MarshallStackfor plainerrors.New/fmt.Errorf errors), then log with.Err(err).Msg("...").With zerolog
v1.34.x, the JSON line includes the error field (default key "error", or whateverErrorFieldNameis set to, e.g. ECSerror.message).With zerolog
v1.35.x, that field is missing: the line typically only has message (and level/timestamp), even thougherris non-nil.Extra Notes / Question
When
ErrorStackMarshaler(err)returnsnil, is it intentional thatErr()no longer records the main error field (i.e.AnErris skipped), or should nil mean only “no value for the stack field”, with the error text still emitted as inv1.34?If the new behaviour is intended, it would help to document that
nilfromErrorStackMarshalersuppresses the entireErr()payload, since that affects common setups (e.g. ECS logging) wherenilonly indicates “no stack trace available” for typical Go errors I think.#748’s description says Context/Fields were restructured when ErrorStackMarshaler returns nil for coverage but it doesn’t define intended behaviour for whether
Err()should still record the error. Was dropping the error field intentional? Or am I maybe doing something wrong?