{"record":{"id":"97e11234df589b7f","repo":"vitessio/vitess","slug":"a-post-request-needs-a-keyspace-in-the-url","errorCode":null,"errorMessage":"a POST request needs a keyspace in the URL","messagePattern":"a POST request needs a keyspace in the URL","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctld/api.go","lineNumber":213,"sourceCode":"\thandleCollection(\"keyspaces\", func(r *http.Request) (any, error) {\n\t\tkeyspace := getItemPath(r.URL.Path)\n\t\tswitch r.Method {\n\t\tcase \"GET\":\n\t\t\t// List all keyspaces.\n\t\t\tif keyspace == \"\" {\n\t\t\t\treturn ts.GetKeyspaces(ctx)\n\t\t\t}\n\t\t\t// Get the keyspace record.\n\t\t\tk, err := ts.GetKeyspace(ctx, keyspace)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// Pass the embedded proto directly or jsonpb will panic.\n\t\t\treturn k.Keyspace, err\n\t\t\t// Perform an action on a keyspace.\n\t\tcase \"POST\":\n\t\t\tif keyspace == \"\" {\n\t\t\t\treturn nil, errors.New(\"a POST request needs a keyspace in the URL\")\n\t\t\t}\n\t\t\tif err := r.ParseForm(); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\taction := r.FormValue(\"action\")\n\t\t\tif action == \"\" {\n\t\t\t\treturn nil, errors.New(\"a POST request must specify action\")\n\t\t\t}\n\t\t\treturn actions.ApplyKeyspaceAction(ctx, action, keyspace), nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"unsupported HTTP method: %v\", r.Method)\n\t\t}\n\t})\n\n\thandleCollection(\"keyspace\", func(r *http.Request) (any, error) {\n\t\t// Valid requests: api/keyspace/my_ks/tablets (all shards)\n\t\t// Valid requests: api/keyspace/my_ks/tablets/-80 (specific shard)","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctld/api.go#L195-L231","documentation":"The keyspaces collection handler in the vtctld HTTP API requires the keyspace to be encoded in the URL for POST requests, because a POST represents an action on a specific keyspace. If the POST path has no keyspace segment, this error is returned before form parsing.","triggerScenarios":"POSTing to /api/keyspaces (no keyspace in the path), e.g. curl -X POST http://vtctld:15000/api/keyspaces -d 'action=Refresh'.","commonSituations":"Scripts that POST keyspace actions to the collection root instead of /api/keyspaces/<keyspace>; automation migrating from vtctl commands where the keyspace was a flag; missing URL encoding of the keyspace.","solutions":["Include the keyspace in the URL: POST /api/keyspaces/<keyspace> with action=<action> in the form body.","If you meant to act on a shard or tablet, use the appropriate endpoint (/api/<keyspace>/shards/... or /api/tablets/...).","Check the client/script builds the URL from the keyspace variable (it may be empty due to an earlier failed lookup)."],"exampleFix":"// before\ncurl -X POST http://localhost:15000/api/keyspaces -d 'action=Refresh'\n// after\ncurl -X POST http://localhost:15000/api/keyspaces/commerce -d 'action=Refresh'","handlingStrategy":"validation","validationCode":"if keyspace == \"\" {\n    return fmt.Errorf(\"cannot POST keyspace action: keyspace is empty\")\n}\nurl := fmt.Sprintf(\"%s/api/keyspaces/%s\", base, url.PathEscape(keyspace))","typeGuard":null,"tryCatchPattern":"resp, err := http.PostForm(base+\"/api/keyspaces/\"+keyspace, url.Values{\"action\": {action}})\nif err != nil { /* handler rejected with 'a POST request needs a keyspace in the URL' - fix the URL */ }","preventionTips":["Interpolate the keyspace into the URL for all keyspace POSTs.","Fail early in clients when the keyspace variable is empty."],"tags":["http-api","vtctld","keyspace","post"],"backgroundTag":"missing-url-parameter","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}