{"id":"ea53ab712cfda496","repo":"gorilla/mux","slug":"key-not-found-in-metadata","errorCode":null,"errorMessage":"key not found in metadata","messagePattern":"key not found in metadata","errorType":"error_code","errorClass":"ErrMetadataKeyNotFound","httpStatus":null,"severity":"error","filePath":"mux.go","lineNumber":28,"sourceCode":"\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"regexp\"\n)\n\nvar (\n\t// ErrMethodMismatch is returned when the method in the request does not match\n\t// the method defined against the route.\n\tErrMethodMismatch = errors.New(\"method is not allowed\")\n\t// ErrNotFound is returned when no route match is found.\n\tErrNotFound = errors.New(\"no matching route was found\")\n\t// RegexpCompileFunc aliases regexp.Compile and enables overriding it.\n\t// Do not run this function from `init()` in importable packages.\n\t// Changing this value is not safe for concurrent use.\n\tRegexpCompileFunc = regexp.Compile\n\t// ErrMetadataKeyNotFound is returned when the specified metadata key is not present in the map\n\tErrMetadataKeyNotFound = errors.New(\"key not found in metadata\")\n)\n\n// NewRouter returns a new router instance.\nfunc NewRouter() *Router {\n\treturn &Router{namedRoutes: make(map[string]*Route)}\n}\n\n// Router registers routes to be matched and dispatches a handler.\n//\n// It implements the http.Handler interface, so it can be registered to serve\n// requests:\n//\n//\tvar router = mux.NewRouter()\n//\n//\tfunc main() {\n//\t    http.Handle(\"/\", router)\n//\t}\n//","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/gorilla/mux/blob/db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265/mux.go#L10-L46","documentation":"Sentinel error mux.ErrMetadataKeyNotFound (mux.go:28). Returned by Route.GetMetadataValue (route.go:155-162) when the requested key is absent from the route's metadata map (populated via Route.Metadata). Lets callers distinguish 'absent key' from 'present with zero value'. The non-erroring alternative is GetMetadataValueOr (route.go:165).","triggerScenarios":"Calling route.GetMetadataValue(\"rateLimit\") on a route that never had .Metadata(\"rateLimit\", v) called, or whose metadata map is nil because no metadata was ever set.","commonSituations":"Middleware reading optional metadata (rate limit, auth role, cache TTL) applied to only some routes; key type drift (string vs custom typed key); refactor renaming a metadata key in the builder but not the middleware.","solutions":["Use route.GetMetadataValueOr(key, default) when a default exists.","Guard with route.MetadataContains(key) first, or read GetMetadata() and use the comma-ok form.","Define metadata keys as typed constants so the key type/value stays consistent."],"exampleFix":"// before\nv, err := route.GetMetadataValue(\"rate\")\n// err == mux.ErrMetadataKeyNotFound on untagged routes\n\n// after\nv := route.GetMetadataValueOr(\"rate\", defaultRate)","handlingStrategy":"fallback","validationCode":"if !route.MetadataContains(key) {\n    return defaultValue\n}","typeGuard":"func hasMetadata(r *mux.Route, key any) bool { return r != nil && r.MetadataContains(key) }","tryCatchPattern":"v, err := route.GetMetadataValue(key)\nif err != nil {\n    if errors.Is(err, mux.ErrMetadataKeyNotFound) {\n        v = fallback\n    } else {\n        return err\n    }\n}","preventionTips":["Prefer GetMetadataValueOr when a default exists.","Centralize metadata key constants (typed).","Set required metadata in the same builder helper that creates the route."],"tags":["metadata","routing","config","sentinel"],"analyzedSha":"db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265","analyzedAt":"2026-08-04T21:35:47.097Z","schemaVersion":2}