{"record":{"id":"1afdb5df365de5ab","repo":"vitessio/vitess","slug":"getsrvvschema-s-w","errorCode":null,"errorMessage":"GetSrvVSchema(%s): %w","messagePattern":"GetSrvVSchema\\((.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/api.go","lineNumber":2759,"sourceCode":"\n\t\tschema = strings.Join(schemas, \";\")\n\t}(c)\n\n\t// GetSrvVSchema\n\tgo func(c *cluster.Cluster) {\n\t\tdefer wg.Done()\n\n\t\tspan, ctx := trace.NewSpan(ctx, \"Cluster.GetSrvVSchema\")\n\t\tdefer span.Finish()\n\n\t\tspan.Annotate(\"cell\", tablet.Tablet.Alias.Cell)\n\t\tcluster.AnnotateSpan(c, span)\n\n\t\tres, err := c.Vtctld.GetSrvVSchema(ctx, &vtctldatapb.GetSrvVSchemaRequest{\n\t\t\tCell: tablet.Tablet.Alias.Cell,\n\t\t})\n\t\tif err != nil {\n\t\t\ter.RecordError(fmt.Errorf(\"GetSrvVSchema(%s): %w\", tablet.Tablet.Alias.Cell, err))\n\t\t\treturn\n\t\t}\n\n\t\tksvs, ok := res.SrvVSchema.Keyspaces[req.Keyspace]\n\t\tif !ok {\n\t\t\ter.RecordError(fmt.Errorf(\"%w: keyspace %s\", errors.ErrNoSrvVSchema, req.Keyspace))\n\t\t\treturn\n\t\t}\n\n\t\tksvsb, err := json.Marshal(&ksvs)\n\t\tif err != nil {\n\t\t\ter.RecordError(err)\n\t\t\treturn\n\t\t}\n\n\t\tsrvVSchema = fmt.Sprintf(`{\"%s\": %s}`, req.Keyspace, string(ksvsb))\n\t}(c)\n","sourceCodeStart":2741,"sourceCodeEnd":2777,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/api.go#L2741-L2777","documentation":"VTEXplain also fetches the per-cell SrvVSchema (the routing rules/vschema deployed to a cell) from vtctld. If the GetSrvVSchema RPC fails, the error is recorded with the cell name and the goroutine aborts. Without the srv vschema the explain cannot resolve routing, so this contributes to a failed request.","triggerScenarios":"The GetSrvVSchema goroutine calls c.Vtctld.GetSrvVSchema for the tablet's cell and the RPC returns an error — vtctld unreachable, timeout, or topo read failure in that cell.","commonSituations":"vtctld is down or being restarted; vtadmin cannot reach vtctld's gRPC port; etcd/zk for the named cell is degraded; misconfigured vtctld address in vtadmin's cluster config.","solutions":["Verify vtctld is running and reachable at the address configured in vtadmin's cluster config.","Retry the request once vtctld is healthy.","Check topo (etcd/zk) health for the cell named in the error.","Test manually: `vtctldclient --server <vtctld> GetSrvVSchema --cell <cell>`.","If the cell name is wrong/uncommon, check the tablet alias cell and the cluster's cells configuration."],"exampleFix":"// before\nres, err := c.Vtctld.GetSrvVSchema(ctx, &vtctldatapb.GetSrvVSchemaRequest{Cell: tablet.Tablet.Alias.Cell})\n// err: rpc unavailable\n// after: point vtadmin at a healthy vtctld\n\"vtctld\": {\"addresses\": [\"localhost:15999\"]} // correct, running vtctld","handlingStrategy":"retry","validationCode":"// Probe vtctld connectivity first\nconn, err := grpc.DialContext(ctx, vtctldAddr, grpc.WithBlock(), grpc.WithTimeout(2*time.Second))\nif err != nil { return fmt.Errorf(\"vtctld %s unreachable: %w\", vtctldAddr, err) }","typeGuard":null,"tryCatchPattern":"res, err := c.Vtctld.GetSrvVSchema(ctx, reqCell)\nif err != nil {\n    if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {\n        // retry with backoff or fail over to another vtctld\n        return retryWithBackoff(3, time.Second, func() error { ... })\n    }\n    return fmt.Errorf(\"GetSrvVSchema(%s): %w\", cell, err)\n}","preventionTips":["Run vtctld behind a highly available address (multiple replicas/LB) and configure vtadmin with all addresses.","Alert on vtctld health so outages are fixed before vtexplain is used.","Verify topo (etcd/zk) health for all cells vtadmin serves."],"tags":["vtadmin","vtexplain","vschema","vtctld","rpc-failure"],"backgroundTag":"vtctld-unreachable","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}