diff --git a/builder.go b/builder.go index b92abd7..07809a5 100644 --- a/builder.go +++ b/builder.go @@ -433,7 +433,7 @@ func (b OopsErrorBuilder) WithContext(ctx context.Context, keys ...any) OopsErro for _, k := range keys { switch k := k.(type) { case fmt.Stringer: - snap[k.String()] = contextValueOrNil(ctx, k.String()) + snap[k.String()] = contextValueOrNil(ctx, k) case string: snap[k] = contextValueOrNil(ctx, k) case *string: diff --git a/context_stringer_test.go b/context_stringer_test.go new file mode 100644 index 0000000..ce21436 --- /dev/null +++ b/context_stringer_test.go @@ -0,0 +1,26 @@ +package oops + +import ( + "context" + "testing" +) + +type stringerContextKey int + +func (k stringerContextKey) String() string { return "request_id" } + +func TestWithContextPreservesStringerKeyIdentity(t *testing.T) { + t.Parallel() + key := stringerContextKey(1) + ctx := context.WithValue(context.Background(), key, "typed value") + // A string key with the same display name must not shadow the typed key. + ctx = context.WithValue(ctx, "request_id", "string value") //nolint:staticcheck,revive + wrapped := WithContext(ctx, key).Errorf("failed") + err, ok := wrapped.(OopsError) + if !ok { + t.Fatalf("unexpected error type: %T", wrapped) + } + if got := err.context["request_id"]; got != "typed value" { + t.Fatalf("context value = %v", got) + } +}