diff --git a/datamodel/low/v3/create_document.go b/datamodel/low/v3/create_document.go index 7ae8f838..bfc06e94 100644 --- a/datamodel/low/v3/create_document.go +++ b/datamodel/low/v3/create_document.go @@ -483,6 +483,11 @@ func extractPaths(ctx context.Context, root *yaml.Node, nodes documentTopLevelNo } func extractWebhooks(ctx context.Context, root *yaml.Node, nodes documentTopLevelNodes, doc *Document, idx *index.SpecIndex) error { + // without a genuine top-level key, ExtractMap can match a same-named scalar + // (e.g. "webhooks" in an extension value) and create an empty webhooks map. + if nodes.webhooks.value == nil { + return nil + } hooks, hooksL, hooksN, err := low.ExtractMap[*PathItem](ctx, WebhooksLabel, root, idx) if err != nil { return err diff --git a/datamodel/low/v3/create_document_test.go b/datamodel/low/v3/create_document_test.go index 9eec996d..873a1eff 100644 --- a/datamodel/low/v3/create_document_test.go +++ b/datamodel/low/v3/create_document_test.go @@ -496,6 +496,28 @@ webhooks: assert.Len(t, utils.UnwrapErrors(err), 1) } +// a "webhooks" scalar value (here in an extension) must not create a webhooks map. +func TestCreateDocument_WebHooks_NoFalsePositive(t *testing.T) { + yml := `openapi: 3.0.3 +info: + title: t + version: "1.0.0" +x-foo: + service: webhooks +paths: + /a: + get: + responses: + '200': + description: OK` + + info, _ := datamodel.ExtractSpecInfo([]byte(yml)) + d, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{}) + require.NoError(t, err) + assert.Nil(t, d.Webhooks.Value) + assert.Nil(t, d.Webhooks.KeyNode) +} + func TestCreateDocument_Servers(t *testing.T) { initTest() assert.Len(t, doc.Servers.Value, 2)