From 621efefcc4e951f9499d0485a8924b39b1e19a5f Mon Sep 17 00:00:00 2001 From: Adam Spiers Date: Tue, 3 Mar 2026 20:58:20 +0000 Subject: [PATCH] lexlint: fix panic in breakingDefs when inner schema type changes The type-change guard compared reflect.TypeOf on the SchemaDef wrapper structs, which are always the same type. This meant the guard never triggered, and bare type assertions like remote.Inner.(SchemaString) would panic when the inner types differed (e.g. SchemaString vs SchemaObject). Fix by comparing the Inner field types instead. --- lex/lexlint/breaking.go | 4 ++-- lex/lexlint/breaking_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 lex/lexlint/breaking_test.go diff --git a/lex/lexlint/breaking.go b/lex/lexlint/breaking.go index 3d82e84c..03295881 100644 --- a/lex/lexlint/breaking.go +++ b/lex/lexlint/breaking.go @@ -55,13 +55,13 @@ func breakingDefs(nsid syntax.NSID, name string, local, remote lexicon.SchemaDef issues := []LintIssue{} // NOTE: in some situations this sort of change might actually be allowed? - if reflect.TypeOf(local) != reflect.TypeOf(remote) { + if reflect.TypeOf(local.Inner) != reflect.TypeOf(remote.Inner) { issues = append(issues, LintIssue{ NSID: nsid, LintLevel: "error", LintName: "type-change", LintDescription: "schema definition type changed", - Message: fmt.Sprintf("schema type changed (%s): %T != %T", name, local, remote), + Message: fmt.Sprintf("schema type changed (%s): %T != %T", name, local.Inner, remote.Inner), }) return issues } diff --git a/lex/lexlint/breaking_test.go b/lex/lexlint/breaking_test.go new file mode 100644 index 00000000..e2213987 --- /dev/null +++ b/lex/lexlint/breaking_test.go @@ -0,0 +1,24 @@ +package lexlint + +import ( + "testing" + + "github.com/bluesky-social/indigo/atproto/lexicon" + + "github.com/stretchr/testify/assert" +) + +func TestBreakingDefs_InnerTypeChange(t *testing.T) { + assert := assert.New(t) + + // When a field changes type (e.g. string -> object), breakingDefs should + // report a type-change error rather than panicking on a type assertion. + local := lexicon.SchemaDef{Inner: lexicon.SchemaString{}} + remote := lexicon.SchemaDef{Inner: lexicon.SchemaObject{}} + + issues := breakingDefs("com.example.test", "testField", local, remote) + + assert.Len(issues, 1) + assert.Equal("type-change", issues[0].LintName) + assert.Equal("error", issues[0].LintLevel) +} -- 2.51.2