diff --git a/error.go b/error.go index 9037b88..f5f602d 100644 --- a/error.go +++ b/error.go @@ -744,8 +744,12 @@ func (o OopsError) ToMap() map[string]any { //nolint:gocyclo if s.userID != "" || len(s.userData) > 0 { // snapshot() owns s.userData (freshly merged in mergeMaps), so it can - // be used directly instead of copying. + // be used directly instead of copying. It is nil when only the user + // ID was set. user := s.userData + if user == nil { + user = map[string]any{} + } if s.userID != "" { user["id"] = s.userID } @@ -754,8 +758,12 @@ func (o OopsError) ToMap() map[string]any { //nolint:gocyclo if s.tenantID != "" || len(s.tenantData) > 0 { // snapshot() owns s.tenantData (freshly merged in mergeMaps), so it can - // be used directly instead of copying. + // be used directly instead of copying. It is nil when only the tenant + // ID was set. tenant := s.tenantData + if tenant == nil { + tenant = map[string]any{} + } if s.tenantID != "" { tenant["id"] = s.tenantID } diff --git a/kv.go b/kv.go index a72810e..bd840a5 100644 --- a/kv.go +++ b/kv.go @@ -303,9 +303,17 @@ func snapshot(o OopsError) OopsError { //nolint:gocyclo } s.tags = lo.Uniq(s.tags) - s.context = dereferencePointers(lazyMapEvaluation(mergeMaps(contextMaps))) - s.userData = dereferencePointers(lazyMapEvaluation(mergeMaps(userDataMaps))) - s.tenantData = dereferencePointers(lazyMapEvaluation(mergeMaps(tenantDataMaps))) + // Only merge when the chain actually carries maps: mergeMaps allocates + // even for empty input, and consumers only ever check len() on these. + if len(contextMaps) > 0 { + s.context = dereferencePointers(lazyMapEvaluation(mergeMaps(contextMaps))) + } + if len(userDataMaps) > 0 { + s.userData = dereferencePointers(lazyMapEvaluation(mergeMaps(userDataMaps))) + } + if len(tenantDataMaps) > 0 { + s.tenantData = dereferencePointers(lazyMapEvaluation(mergeMaps(tenantDataMaps))) + } return s }