gin-gonic/gin · critical
key %v does not exist
Error message
key %v does not exist
What it means
Context.MustGet (context.go:310) panics with this message when the requested key is not present in c.Keys. Unlike Get (which returns ok=false), MustGet is designed for mandatory values and intentionally panics to surface programmer error; recovery middleware will turn it into a 500 unless intercepted.
Source
Thrown at context.go:310
c.Keys[key] = value
}
// Get returns the value for the given key, ie: (value, true).
// If the value does not exist it returns (nil, false)
func (c *Context) Get(key any) (value any, exists bool) {
c.mu.RLock()
defer c.mu.RUnlock()
value, exists = c.Keys[key]
return
}
// MustGet returns the value for the given key if it exists, otherwise it panics.
func (c *Context) MustGet(key any) any {
if value, exists := c.Get(key); exists {
return value
}
panic(fmt.Sprintf("key %v does not exist", key))
}
func getTyped[T any](c *Context, key any) (res T) {
if val, ok := c.Get(key); ok && val != nil {
res, _ = val.(T)
}
return
}
// GetString returns the value associated with the key as a string.
func (c *Context) GetString(key any) string {
return getTyped[string](c, key)
}
// GetBool returns the value associated with the key as a boolean.
func (c *Context) GetBool(key any) bool {
return getTyped[bool](c, key)
}View on GitHub (pinned to 34dac209ff)
Solutions
- Use c.Get(key) and handle the exists==false case instead of MustGet when the value may legitimately be absent.
- Ensure the middleware that calls c.Set runs before any handler that calls MustGet (order matters in the chain).
- Use a typed accessor (c.MustGet("user").(*User)) only after guaranteeing the Set, and centralise key strings as constants.
Example fix
// before
user := c.MustGet("user").(*User)
// after
val, ok := c.Get("user")
if !ok { c.AbortWithStatus(http.StatusUnauthorized); return }
user := val.(*User) Defensive patterns
Strategy: try-catch
Validate before calling
if _, ok := c.Get("user"); !ok {
c.AbortWithStatus(http.StatusUnauthorized)
return
} Try / catch
defer func() {
if r := recover(); r != nil {
if s, ok := r.(string); ok && strings.HasPrefix(s, "key ") && strings.Contains(s, "does not exist") {
c.AbortWithStatus(http.StatusInternalServerError)
}
}
}()
val := c.MustGet(key) Prevention
- Prefer c.Get over c.MustGet unless the key is guaranteed by middleware.
- Order middleware so any Set runs before any MustGet.
- Keep context keys in a typed constants package to avoid typos.
When it happens
Trigger: Calling c.MustGet("user") when no prior middleware did c.Set("user", ...); typo in the key ("User" vs "user"); calling MustGet before the middleware that sets it in the chain; key set under a different type (e.g. *User vs User) but that returns nil not panic.
Common situations: Auth middleware ordering (MustGet called before Set runs); refactoring a key name in one place but not another; conditional Set that skipped on an early Abort.
Related errors
- cannot read nil body
- gin mode unknown: ${value} (available mode: debug release te
- the HTML debug render was created without files or glob patt
- Cannot redirect with status code %d
- http method ${httpMethod} is not valid
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/7d334ecccb490d76.json.
Report an issue: GitHub.