{"record":{"id":"10e982c2f53fe5eb","repo":"vitessio/vitess","slug":"invalid-throttlerz-path","errorCode":null,"errorMessage":"invalid /throttlerz path","messagePattern":"invalid /throttlerz path","errorType":"http","errorClass":null,"httpStatus":404,"severity":"info","filePath":"go/vt/throttler/throttlerz.go","lineNumber":65,"sourceCode":"\nvar (\n\tlistTemplate = template.Must(template.New(\"list\").Parse(listHTML))\n\n\tdetailsTemplate = template.Must(template.New(\"details\").Parse(detailsHTML))\n)\n\nfunc init() {\n\tservenv.HTTPHandleFunc(\"/throttlerz/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tthrottlerzHandler(w, r, GlobalManager)\n\t})\n}\n\nfunc throttlerzHandler(w http.ResponseWriter, r *http.Request, m *managerImpl) {\n\t// Longest supported URL: /throttlerz/<name>\n\tparts := strings.SplitN(r.URL.Path, \"/\", 3)\n\n\tif len(parts) != 3 {\n\t\thttp.Error(w, \"invalid /throttlerz path\", http.StatusNotFound)\n\t\treturn\n\t}\n\n\tname := parts[2]\n\tif name == \"\" {\n\t\tlistThrottlers(w, m)\n\t\treturn\n\t}\n\n\tif !slices.Contains(m.Throttlers(), name) {\n\t\thttp.Error(w, \"throttler not found\", http.StatusNotFound)\n\t\treturn\n\t}\n\n\tshowThrottlerDetails(w, name)\n}\n\nfunc listThrottlers(w http.ResponseWriter, m *managerImpl) {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/throttler/throttlerz.go#L47-L83","documentation":"throttlerzHandler mirrors throttlerlogz: it splits the URL path into at most 3 '/'-separated segments and requires exactly 3 (/throttlerz/<name>). Fewer segments returns 404 'invalid /throttlerz path'. The bare /throttlerz path itself is registered separately as the list view; this handler expects a name.","triggerScenarios":"A request routed to throttlerzHandler with a path like '/throttlerz' (no trailing slash) yielding only 2 parts from strings.SplitN, or any path not shaped like /throttlerz/<name>.","commonSituations":"Scripts appending the throttler name without the separating slash or with a doubled/missing slash; proxies normalizing away the trailing slash; hand-written tests/monitoring checks hitting the wrong path shape.","solutions":["Use /throttlerz (exact) for the list view, or /throttlerz/<name> for details.","Ensure exactly one slash separates 'throttlerz' and the name (avoid //throttlerz or /throttlerz//name).","Check reverse-proxy rules for path rewriting that collapses slashes or strips the trailing segment.","Update monitoring scripts to use the canonical URL shape."],"exampleFix":"// before\ncurl http://localhost:15000/throttlerzmy-throttler\n// after\ncurl http://localhost:15000/throttlerz/my-throttler","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(base)\nu.Path = path.Join(\"/throttlerz\", name)\nif name == \"\" {\n\tu.Path = \"/throttlerz\"\n}\nreq := u.String()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use path.Join to construct /throttlerz/<name> URLs; never concatenate.","Distinguish the list view (/throttlerz) from the detail view (/throttlerz/<name>) in tooling.","Verify proxy rewrite rules preserve single-slash path structure."],"tags":["http","routing","url","throttler"],"backgroundTag":"invalid-url-path","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}