gin-gonic/gin · critical

URL parameters can not be used when serving a static file

Error message

URL parameters can not be used when serving a static file

What it means

staticFileHandler (routergroup.go:183) panics when the relativePath passed to StaticFile / StaticFileFS contains ':' or '*', because static file routes serve a fixed path and URL parameters are meaningless there. The check runs at registration time, so this surfaces during server startup.

Source

Thrown at routergroup.go:183

// router.StaticFile("favicon.ico", "./resources/favicon.ico")
func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes {
	return group.staticFileHandler(relativePath, func(c *Context) {
		c.File(filepath)
	})
}

// StaticFileFS works just like `StaticFile` but a custom `http.FileSystem` can be used instead.
// router.StaticFileFS("favicon.ico", "./resources/favicon.ico", Dir{".", false})
// Gin by default uses: gin.Dir()
func (group *RouterGroup) StaticFileFS(relativePath, filepath string, fs http.FileSystem) IRoutes {
	return group.staticFileHandler(relativePath, func(c *Context) {
		c.FileFromFS(filepath, fs)
	})
}

func (group *RouterGroup) staticFileHandler(relativePath string, handler HandlerFunc) IRoutes {
	if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
		panic("URL parameters can not be used when serving a static file")
	}
	group.GET(relativePath, handler)
	group.HEAD(relativePath, handler)
	return group.returnObj()
}

// Static serves files from the given file system root.
// Internally a http.FileServer is used, therefore http.NotFound is used instead
// of the Router's NotFound handler.
// To use the operating system's file system implementation,
// use :
//
//	router.Static("/static", "/var/www")
func (group *RouterGroup) Static(relativePath, root string) IRoutes {
	return group.StaticFS(relativePath, Dir(root, false))
}

// StaticFS works just like `Static()` but a custom `http.FileSystem` can be used instead.

View on GitHub (pinned to 34dac209ff)

Solutions

  1. For a single fixed file use a literal path with no params: router.StaticFile("/favicon.ico", "./public/favicon.ico").
  2. For dynamic per-request files use a normal GET handler with c.Param and c.File(filepath.Join(...)).
  3. For a directory tree use router.Static("/assets", "./public") which handles /*filepath internally.

Example fix

// before
router.StaticFile("/assets/:name", "./public/logo.png")
// after
router.StaticFile("/assets/logo.png", "./public/logo.png")
// or for dynamic:
router.GET("/assets/:name", func(c *gin.Context) {
    c.File(filepath.Join("./public", c.Param("name")))
})
Defensive patterns

Strategy: validation

Validate before calling

if strings.ContainsAny(relativePath, ":*") {
    log.Fatalf("static file path %q must not contain URL parameters", relativePath)
}
router.StaticFile(relativePath, filepath)

Prevention

When it happens

Trigger: router.StaticFile("/assets/:name", file) — trying to parametrise a static file route; router.StaticFile("/files/*path", file) — wildcard on a single-file route.

Common situations: Confusing StaticFile (one fixed file) with Static/StaticFS (a directory tree that supports /*filepath); trying to use path params on a static file handler.

Related errors


AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04). Data as JSON: /data/errors/d2c67ee7d4c054e5.json. Report an issue: GitHub.