gin-contrib / gin-contrib/timeout

Unmatched routes respond `200 OK` with empty body when middleware is registered globally via Use()

Open
#87 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
237
Forks
42
Avg merge
3d 3h
Merged PRs (30d)
2

Description

When the timeout middleware is registered globally with engine.Use(...), any request that does not match a registered route is answered with 200 OK and an empty body instead of gin's default 404 page not found.

Gin's own access logger still reports 404, so the internal status and the status actually sent on the wire disagree, which makes this very confusing to debug behind a reverse proxy (our ingress logged 200 while the app logged 404).

Registering the middleware per-route (as in _example/example01) does not trigger the bug, because route-level handlers never run for unmatched routes. The examples therefore never exercise this path.

How to reproduce

package main

import (
	"net/http"
	"time"

	"github.com/gin-contrib/timeout"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.New()
	r.Use(gin.Logger(), timeout.New(timeout.WithTimeout(30*time.Second)))
	r.GET("/hello", func(c *gin.Context) {
		c.String(http.StatusOK, "world")
	})
	_ = http.ListenAndServe(":8080", r)
}
$ curl -si http://127.0.0.1:8080/no/such/route
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 0

Server log for the same request (note the 404):

[GIN] 2026/07/30 - 17:14:57 | 404 | 57.607µs | 127.0.0.1 | GET "/no/such/route"

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with gin.New(), a global timeout.New middleware, the /hello route, and a request to /no/such/route. Start by tracing how the globally registered middleware interacts with Gin's unmatched-route handling and compare the access-log status with the response sent by curl. Done means an unmatched route returns Gin's default 404 page not found response on the wire while routed requests and timeout behavior remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.