From 8e743cbfeb8e0dbb2b3a605a93c2acc754024d27 Mon Sep 17 00:00:00 2001 From: iceymoss <114280774+iceymoss@users.noreply.github.com> Date: Sat, 28 Mar 2026 04:02:58 +0800 Subject: [PATCH] fix(event): prevent panic on non-string telemetry keys (#2502) --- internal/event/event.go | 6 +++++- internal/event/event_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/internal/event/event.go b/internal/event/event.go index a10b5d82b7fdf13ccf02fd0967cab2ce65e20661..a809e214db8b6cc3134a04b561683742b0565e26 100644 --- a/internal/event/event.go +++ b/internal/event/event.go @@ -127,7 +127,11 @@ func pairsToProps(props ...any) posthog.Properties { } for i := 0; i < len(props); i += 2 { - key := props[i].(string) + key, ok := props[i].(string) + if !ok { + slog.Error("Event property key must be a string", "key", props[i], "index", i) + continue + } value := props[i+1] p = p.Set(key, value) } diff --git a/internal/event/event_test.go b/internal/event/event_test.go index 7cd22248f19ca072853cd4270ae6fc36e4c124f5..17a44568453f251f6b77ab8749c10a8cd92d7f15 100644 --- a/internal/event/event_test.go +++ b/internal/event/event_test.go @@ -4,7 +4,10 @@ package event // scenarios. These tests will not log anything. import ( + "reflect" "testing" + + "github.com/posthog/posthog-go" ) func TestError(t *testing.T) { @@ -59,6 +62,33 @@ func TestError(t *testing.T) { }) } +func TestPairsToProps(t *testing.T) { + t.Run("sets valid key value pairs", func(t *testing.T) { + got := pairsToProps("foo", "bar", "count", 3) + want := posthog.NewProperties(). + Set("foo", "bar"). + Set("count", 3) + if !reflect.DeepEqual(got, want) { + t.Fatalf("pairsToProps() = %#v, want %#v", got, want) + } + }) + + t.Run("returns empty properties for odd pairs", func(t *testing.T) { + got := pairsToProps("foo", "bar", "count") + if len(got) != 0 { + t.Fatalf("pairsToProps() should return empty properties, got %#v", got) + } + }) + + t.Run("ignores non-string key and continues", func(t *testing.T) { + got := pairsToProps(123, "bad", "ok", true) + want := posthog.NewProperties().Set("ok", true) + if !reflect.DeepEqual(got, want) { + t.Fatalf("pairsToProps() = %#v, want %#v", got, want) + } + }) +} + // newDefaultTestError creates a test error that mimics runtime panic // errors. This helps us testing that the Error function can handle various // error types, including those that might be passed from a panic recovery