#2207·swag

v2 --v3.1: panic (nil pointer dereference) on query object fields of named types

Author: thommeoCreated Jul 28, 2026Updated Jul 28, 2026

Describe the bug

With OpenAPI 3.1 output (swag init --v3.1), swag panics with a nil pointer dereference when a struct used as an object query parameter has a field whose type is a named Go type rather than a builtin primitive.

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0xf8]

github.com/swaggo/swag/v2.(*OperationV3).ParseParamComment(...)
	github.com/swaggo/swag/[email protected]/operationv3.go:399
github.com/swaggo/swag/v2.(*OperationV3).ParseComment(...)
	github.com/swaggo/swag/[email protected]/operationv3.go:85
github.com/swaggo/swag/v2.(*Parser).ParseRouterAPIInfoV3(...)
	github.com/swaggo/swag/[email protected]/parserv3.go:543

The Swagger 2.0 code path and swag v1 handle the same input correctly, so this is specific to the OpenAPI 3 generator.

To Reproduce

main.go:

go
package main

// Include is a named string type with enum constants.
type Include string

const (
	IncludeAuthor   Include = "author"
	IncludeComments Include = "comments"
)

// Query is bound from the query string.
type Query struct {
	Includes []Include `json:"include"`
	Limit    int       `json:"limit"`
}

// ListPosts lists posts.
//
//	@Summary	List posts
//	@Param		query	query		Query	true	"query"
//	@Success	200		{string}	string
//	@Router		/posts [get]
func ListPosts() {}

//	@title		Repro API
//	@version	1.0
func main() {}
bash
$ swag init --v3.1 -g main.go -o ./docs
2026/07/28 22:07:45 Generating main.Query
2026/07/28 22:07:45 Generating main.Include
panic: runtime error: invalid memory address or nil pointer dereference
...

Dropping --v3.1 (Swagger 2.0 output) succeeds and produces the expected spec, so the crash is limited to the v3 generator.

Affected field shapes

Every field whose type is a named type crashes; only builtin primitives survive. Two distinct panic sites are involved:

Field Result on v2.0.0-rc5 Line
Includes []Include (named string with consts) panic operationv3.go:399
Include Include (named string with consts) panic operationv3.go:390
Items []Nested (named struct) panic operationv3.go:399
Item Nested (named struct) panic operationv3.go:390
Includes []string works
Limit int works

Root cause

ParseParamComment expands an object query parameter by iterating the properties of the struct schema:

go
for name, item := range schema.Spec.Properties {
	prop := item.Spec
	if len(*prop.Type) == 0 {
		continue
	}

	itemParam := param

	switch {
	case (*prop.Type)[0] == ARRAY &&
		prop.Items.Schema != nil &&
		len(*prop.Items.Schema.Spec.Type) > 0 &&
		IsSimplePrimitiveType((*prop.Items.Schema.Spec.Type)[0]):
	...

A property whose type is a named Go type is emitted as a $ref into #/components/schemas/..., i.e. a spec.RefOrSpec[spec.Schema] with Ref set and Spec == nil. The loop never resolves the reference:

  • prop := item.Spec is nil for a $ref property, so *prop.Type dereferences nil — this is the scalar case.
  • For a slice of a named type the outer property does have a spec (type: array), but its Items.Schema is a $ref. The prop.Items.Schema != nil guard passes while prop.Items.Schema.Spec is still nil, so *prop.Items.Schema.Spec.Type dereferences nil — this is the slice case.

The Swagger 2.0 implementation of the same loop (operation.go) does resolve references, via parser.getUnderlyingSchema, and additionally guards itemSchema for nil. The v3 port dropped both. This is the same class of bug as #2115 ("prevent panic when parsing custom string types with form tags in OpenAPI v3"), which fixed one other place where a $ref property's Spec was assumed non-nil.

Expected behavior

Match the Swagger 2.0 output: resolve the reference, expand named scalar and slice element types to their underlying type plus enum values, and skip fields whose underlying type is an object (swag already logs skip field [...] is not supported type for query for those).

Swagger 2.0 output for the reproducer above:

json
[
  {
    "type": "array",
    "items": { "type": "string", "enum": ["author", "comments"] },
    "collectionFormat": "csv",
    "name": "include",
    "in": "query"
  }
]

Your swag version

v2.0.0-rc5 (also reproduces on the current v2 branch, 8561606)

Your go version

go1.26.3 darwin/arm64 (also reproduces with go1.24.2)

Additional context

Happy to open a PR — I have a fix and a regression test ready. It adds a getUnderlyingSchemaV3 helper mirroring the v1 getUnderlyingSchema, and resolves the property (and array item) reference before inspecting its type.

Unrelated, but in the same function: operationv3.go:344 (rc5) has a leftover fmt.Println(schema.Spec.Type) that prints a raw type array to stdout whenever a @Param names an enum type. Let me know if you would like that removed in the same PR or a separate one.