{"record":{"id":"52445aff51acd3ce","repo":"vitessio/vitess","slug":"must-specify-action","errorCode":null,"errorMessage":"must specify action","messagePattern":"must specify action","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctld/api.go","lineNumber":311,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"invalid shard path: %q\", shardPath)\n\t\t}\n\t\tparts := strings.SplitN(shardPath, \"/\", 2)\n\t\tkeyspace := parts[0]\n\t\tshard := parts[1]\n\n\t\t// List the shards in a keyspace.\n\t\tif shard == \"\" {\n\t\t\treturn ts.GetShardNames(ctx, keyspace)\n\t\t}\n\n\t\t// Perform an action on a shard.\n\t\tif r.Method == \"POST\" {\n\t\t\tif err := r.ParseForm(); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taction := r.FormValue(\"action\")\n\t\t\tif action == \"\" {\n\t\t\t\treturn nil, errors.New(\"must specify action\")\n\t\t\t}\n\t\t\treturn actions.ApplyShardAction(ctx, action, keyspace, shard), nil\n\t\t}\n\n\t\t// Get the shard record.\n\t\tsi, err := ts.GetShard(ctx, keyspace, shard)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Pass the embedded proto directly or jsonpb will panic.\n\t\treturn si.Shard, err\n\t})\n\n\t// SrvKeyspace\n\thandleCollection(\"srv_keyspace\", func(r *http.Request) (any, error) {\n\t\tkeyspacePath := getItemPath(r.URL.Path)\n\t\tparts := strings.SplitN(keyspacePath, \"/\", 2)\n","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctld/api.go#L293-L329","documentation":"The shard-level HTTP handler accepts POST requests as shard actions; the 'action' form field selects which action to apply via ApplyShardAction. An empty action value produces this error, mirroring the keyspaces handler behavior.","triggerScenarios":"POST to /api/<keyspace>/shards/<shard> (or /api/<keyspace>/tablets/<shard> path form) without an 'action' form field or with action= empty.","commonSituations":"Form field typo ('operation', 'cmd'); JSON body instead of form-encoded; scripts that compute the action conditionally and end up with an empty string.","solutions":["Include action=<name> in the POST form body with a shard action recognized by ApplyShardAction.","Send the body as application/x-www-form-urlencoded.","Log/inspect the request before sending to confirm the action string is populated."],"exampleFix":"// before\ncurl -X POST http://localhost:15000/api/commerce/shards/0 -d ''\n// after\ncurl -X POST http://localhost:15000/api/commerce/shards/0 -d 'action=RebuildKeyspaceGraph'","handlingStrategy":"validation","validationCode":"if action == \"\" {\n    return fmt.Errorf(\"shard POST requires a non-empty 'action' form field\")\n}\nform := url.Values{\"action\": {action}}","typeGuard":null,"tryCatchPattern":"resp, err := http.PostForm(shardURL, form)\nif err != nil || resp.StatusCode != http.StatusOK {\n    // 'must specify action' - ensure action field present\n}","preventionTips":["Always populate the action form field on shard POSTs.","Cross-check action names against ApplyShardAction's supported actions."],"tags":["http-api","vtctld","shard","action"],"backgroundTag":"missing-required-argument","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}