#2216·swag

`@Tags` with empty values generates empty-string tags in Swagger output

Author: AleksaMCodeCreated Aug 24, 2026Updated Aug 25, 2026

When using @Tags with empty values (for example @Tags, @Tags ,, or mixed @Tags tag1, ,tag2), swag generates empty-string entries in the operation tags array (e.g. [""], ["", ""], ["tag1", "", "tag2"]) instead of filtering empties or treating it as untagged.

To Reproduce Steps to reproduce the behavior:

  1. Create a Go API project using swag init and gin-swagger.
  2. Add endpoints with these annotations:
  • // @Tags
  • // @Tags ,
  • // @Tags tag1, ,tag2
  1. Run swag init to generate docs.
  2. Open generated swagger.json (or /swagger/doc.json) and inspect operation tags.

Example I've used to generated the screenshot output below:

go
func main() {
	r := gin.Default()

	r.GET("/tournaments/:id", getTournamentByID)
	r.GET("/health", getHealth)
	r.GET("/about", getAbout)
	r.GET("/tags-comma-only", getTagsCommaOnly)
	r.GET("/tags-mixed", getTagsMixed)

	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

	_ = r.Run(":8082")
}

// getTournamentByID godoc
// @Summary Get tournament by ID
// @Description Fake endpoint for local Swagger tag tests
// @Tags
// @Produce json
// @Param id path string true "Tournament ID"
// @Success 200 {object} map[string]any
// @Router /tournaments/{id} [get]
func getTournamentByID(c *gin.Context) {
	id := c.Param("id")

	c.JSON(http.StatusOK, gin.H{
		"id":     id,
		"name":   "Mock Tournament",
		"status": "scheduled",
	})
}

// getHealth godoc
// @Summary Health check
// @Description Reference endpoint with a normal tag
// @Tags reference
// @Produce json
// @Success 200 {object} map[string]any
// @Router /health [get]
func getHealth(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"status": "ok",
	})
}

// getAbout godoc
// @Summary About endpoint
// @Description Endpoint without explicit tags annotation
// @Produce json
// @Success 200 {object} map[string]any
// @Router /about [get]
func getAbout(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"service": "gin-empty-tags",
		"mode":    "demo",
	})
}

// getTagsCommaOnly godoc
// @Summary Tags comma-only endpoint
// @Description Endpoint using comma-only tags annotation
// @Tags ,
// @Produce json
// @Success 200 {object} map[string]any
// @Router /tags-comma-only [get]
func getTagsCommaOnly(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"case": "comma-only-tags",
	})
}

// getTagsMixed godoc
// @Summary Tags mixed endpoint
// @Description Endpoint using mixed empty and non-empty tags annotation
// @Tags tag1, ,tag2
// @Produce json
// @Success 200 {object} map[string]any
// @Router /tags-mixed [get]
func getTagsMixed(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"case": "mixed-tags",
	})
}

Expected behavior Empty tag tokens should be ignored. Examples:

  • @Tags -> no tags (untagged operation)
  • @Tags , -> no tags
  • @Tags tag1, ,tag2 -> ["tag1", "tag2"]

Screenshots

Image

Your swag version 1.16.6

Your go version 1.25.5

Desktop (please complete the following information):

  • OS: Windows
  • Browser: Firefox
  • Version: -

Additional context Output from doc.json:

{
    "schemes": [],
    "swagger": "2.0",
    "host": "",
    "basePath": "/",
    "paths": {
        "/about": {
            "get": {
                "description": "Endpoint without explicit tags annotation",
                "produces": [
                    "application/json"
                ],
                "summary": "About endpoint",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/health": {
            "get": {
                "description": "Reference endpoint with a normal tag",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "reference"
                ],
                "summary": "Health check",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/tags-comma-only": {
            "get": {
                "description": "Endpoint using comma-only tags annotation",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "",
                    ""
                ],
                "summary": "Tags comma-only endpoint",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/tags-mixed": {
            "get": {
                "description": "Endpoint using mixed empty and non-empty tags annotation",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "tag1",
                    "",
                    "tag2"
                ],
                "summary": "Tags mixed endpoint",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/tournaments/{id}": {
            "get": {
                "description": "Fake endpoint for local Swagger tag tests",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    ""
                ],
                "summary": "Get tournament by ID",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Tournament ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        }
    }
}