{"record":{"id":"87021acb596253a2","repo":"vitessio/vitess","slug":"w-keyspace-name-is-required","errorCode":null,"errorMessage":"%w: keyspace name is required","messagePattern":"%w: keyspace name is required","errorType":"validation","errorClass":"ErrInvalidRequest","httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/api.go","lineNumber":2615,"sourceCode":"\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn res, nil\n}\n\n// VExplain is part of the vtadminpb.VTAdminServer interface.\nfunc (api *API) VExplain(ctx context.Context, req *vtadminpb.VExplainRequest) (*vtadminpb.VExplainResponse, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"API.VExplain\")\n\tdefer span.Finish()\n\n\tif req.ClusterId == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: clusterID is required\", errors.ErrInvalidRequest)\n\t}\n\n\tif req.Keyspace == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: keyspace name is required\", errors.ErrInvalidRequest)\n\t}\n\n\tif req.Sql == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: SQL query is required\", errors.ErrInvalidRequest)\n\t}\n\n\tc, err := api.getClusterForRequest(req.ClusterId)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !api.authz.IsAuthorized(ctx, c.ID, rbac.VExplainResource, rbac.GetAction) {\n\t\treturn nil, nil\n\t}\n\n\t// Parser with default options. New() itself initializes with default MySQL version.\n\tparser, err := sqlparser.New(sqlparser.Options{\n\t\tTruncateUILen:  512,","sourceCodeStart":2597,"sourceCodeEnd":2633,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/api.go#L2597-L2633","documentation":"Returned by vtadmin API methods (wrapping a sentinel error) when a request omits the required keyspace name, e.g. StartWorkflow/GetWorkflow calls on a keyspace-scoped resource.","triggerScenarios":"Calling API.VExplain with ClusterId set but Keyspace equal to \"\".","commonSituations":"Query built from a context where the keyspace wasn't selected; UI sends the raw SQL without an attached keyspace; SQL already fully qualified but the API still requires the explicit keyspace field.","solutions":["Populate req.Keyspace with the target keyspace name","Fully qualify table names in SQL only as a complement — still set Keyspace as required by the API","Add client-side validation for keyspace presence"],"exampleFix":"// before\n{clusterId: \"prod-main\", sql: \"select * from t\"}\n// after\n{clusterId: \"prod-main\", keyspace: \"commerce\", sql: \"select * from t\"}","handlingStrategy":"validation","validationCode":"if req.Keyspace == \"\" {\n    return errors.New(\"keyspace is required for vexplain\")\n}","typeGuard":"func hasKeyspace(req *vtadminpb.VExplainRequest) bool {\n    return req != nil && req.Keyspace != \"\"\n}","tryCatchPattern":"if !hasKeyspace(req) {\n    return errors.New(\"keyspace is required for vexplain\")\n}\nresp, err := client.VExplain(ctx, req)","preventionTips":["Bind the keyspace in UI/CLI context before submitting queries","Validate keyspace against the known keyspace list for the cluster","Use one request-construction helper so all required fields are set together"],"tags":["vtadmin","validation","request","keyspace"],"backgroundTag":"missing-required-request-field","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}