vitessio/vitess · error

a POST request needs a keyspace in the URL

Error message

a POST request needs a keyspace in the URL

What it means

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.

Source

Thrown at go/vt/vtctld/api.go:213

	handleCollection("keyspaces", func(r *http.Request) (any, error) {
		keyspace := getItemPath(r.URL.Path)
		switch r.Method {
		case "GET":
			// List all keyspaces.
			if keyspace == "" {
				return ts.GetKeyspaces(ctx)
			}
			// Get the keyspace record.
			k, err := ts.GetKeyspace(ctx, keyspace)
			if err != nil {
				return nil, err
			}
			// Pass the embedded proto directly or jsonpb will panic.
			return k.Keyspace, err
			// Perform an action on a keyspace.
		case "POST":
			if keyspace == "" {
				return nil, errors.New("a POST request needs a keyspace in the URL")
			}
			if err := r.ParseForm(); err != nil {
				return nil, err
			}

			action := r.FormValue("action")
			if action == "" {
				return nil, errors.New("a POST request must specify action")
			}
			return actions.ApplyKeyspaceAction(ctx, action, keyspace), nil
		default:
			return nil, fmt.Errorf("unsupported HTTP method: %v", r.Method)
		}
	})

	handleCollection("keyspace", func(r *http.Request) (any, error) {
		// Valid requests: api/keyspace/my_ks/tablets (all shards)
		// Valid requests: api/keyspace/my_ks/tablets/-80 (specific shard)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Include the keyspace in the URL: POST /api/keyspaces/<keyspace> with action=<action> in the form body.
  2. If you meant to act on a shard or tablet, use the appropriate endpoint (/api/<keyspace>/shards/... or /api/tablets/...).
  3. Check the client/script builds the URL from the keyspace variable (it may be empty due to an earlier failed lookup).

Example fix

// before
curl -X POST http://localhost:15000/api/keyspaces -d 'action=Refresh'
// after
curl -X POST http://localhost:15000/api/keyspaces/commerce -d 'action=Refresh'
Defensive patterns

Strategy: validation

Validate before calling

if keyspace == "" {
    return fmt.Errorf("cannot POST keyspace action: keyspace is empty")
}
url := fmt.Sprintf("%s/api/keyspaces/%s", base, url.PathEscape(keyspace))

Try / catch

resp, err := http.PostForm(base+"/api/keyspaces/"+keyspace, url.Values{"action": {action}})
if err != nil { /* handler rejected with 'a POST request needs a keyspace in the URL' - fix the URL */ }

Prevention

When it happens

Trigger: POSTing to /api/keyspaces (no keyspace in the path), e.g. curl -X POST http://vtctld:15000/api/keyspaces -d 'action=Refresh'.

Common situations: 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.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/97e11234df589b7f. Report an issue: GitHub.