{"record":{"id":"3c468481dda8423d","repo":"vitessio/vitess","slug":"w-request-cannot-be-nil","errorCode":null,"errorMessage":"%w: request cannot be nil","messagePattern":"%w: request cannot be nil","errorType":"validation","errorClass":"errors.ErrInvalidRequest","httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/cluster/cluster.go","lineNumber":429,"sourceCode":"\tdefer span.Finish()\n\n\tAnnotateSpan(c, span)\n\tspan.Annotate(\"keyspace\", req.Keyspace)\n\tspan.Annotate(\"uuid\", req.Uuid)\n\n\treturn c.Vtctld.CompleteSchemaMigration(ctx, req)\n}\n\n// CreateKeyspace creates a keyspace in the given cluster, proxying a\n// CreateKeyspaceRequest to a vtctld in that cluster.\nfunc (c *Cluster) CreateKeyspace(ctx context.Context, req *vtctldatapb.CreateKeyspaceRequest) (*vtadminpb.Keyspace, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"Cluster.CreateKeyspace\")\n\tdefer span.Finish()\n\n\tAnnotateSpan(c, span)\n\n\tif req == nil {\n\t\treturn nil, fmt.Errorf(\"%w: request cannot be nil\", errors.ErrInvalidRequest)\n\t}\n\n\tif req.Name == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: keyspace name is required\", errors.ErrInvalidRequest)\n\t}\n\n\tspan.Annotate(\"keyspace\", req.Name)\n\n\tif err := c.topoRWPool.Acquire(ctx); err != nil {\n\t\treturn nil, fmt.Errorf(\"CreateKeyspace(%+v) failed to acquire topoRWPool: %w\", req, err)\n\t}\n\tdefer c.topoRWPool.Release()\n\n\tresp, err := c.Vtctld.CreateKeyspace(ctx, req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/cluster/cluster.go#L411-L447","documentation":"CreateKeyspace validates its request before doing any work and returns errors.ErrInvalidRequest wrapped with this message when the caller passes a nil *vtctldatapb.CreateKeyspaceRequest. It is a defensive guard so the RPC layer fails fast with a typed invalid-request error instead of panicking on a nil dereference.","triggerScenarios":"Calling Cluster.CreateKeyspace(ctx, nil) directly from Go code, or an RPC/HTTP handler that forwards a nil request into the vtadmin API without first checking it.","commonSituations":"Hand-written clients calling the vtadmin API Go package directly; gRPC handlers receiving a nil request message; tests invoking CreateKeyspace without constructing a request.","solutions":["Pass a non-nil *vtctldatapb.CreateKeyspaceRequest, e.g. &vtctldatapb.CreateKeyspaceRequest{Name: \"commerce\"}.","If calling through an HTTP/JSON layer, ensure the request body deserializes into a request object rather than nil.","Guard your own call site with `if req == nil` before invoking CreateKeyspace."],"exampleFix":"// before\nresp, err := cluster.CreateKeyspace(ctx, nil)\n// after\nreq := &vtctldatapb.CreateKeyspaceRequest{Name: \"commerce\"}\nresp, err := cluster.CreateKeyspace(ctx, req)","handlingStrategy":"try-catch","validationCode":"if req == nil {\n\treturn errors.New(\"CreateKeyspace requires a non-nil request\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := cluster.CreateKeyspace(ctx, req)\nif err != nil {\n\tif errors.Is(err, vtadminerrors.ErrInvalidRequest) && strings.Contains(err.Error(), \"request cannot be nil\") {\n\t\t// fix the call site: construct a request object\n\t\treturn fmt.Errorf(\"bug in caller: nil CreateKeyspaceRequest: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Always construct request structs explicitly; never pass nil protobuf requests to vtadmin Cluster methods.","Centralize vtadmin calls in helpers that default-construct requests.","Cover API helpers with tests that assert non-nil requests are built."],"tags":["vtadmin","validation","invalid-request","keyspace"],"backgroundTag":"nil-request-invalid-request","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}