{"record":{"id":"b337b06c33ed04ea","repo":"vitessio/vitess","slug":"opts-v-err-w","errorCode":null,"errorMessage":"opts %+v, err: %w","messagePattern":"opts %\\+v, err: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/cluster/cluster.go","lineNumber":1570,"sourceCode":"\tif rec.HasErrors() {\n\t\treturn nil, rec.Error()\n\t}\n\n\t// Now, fan out to collect the schemas.\n\tfor _, ks := range keyspaces {\n\t\twg.Add(1)\n\t\tgo func(ctx context.Context, ks *vtadminpb.Keyspace) {\n\t\t\tdefer wg.Done()\n\n\t\t\ttablets, err := c.getTabletsToQueryForSchemas(ctx, ks.Keyspace.Name, tablets, opts)\n\t\t\tif err != nil {\n\t\t\t\t// Ignore keyspaces without any serving tablets.\n\t\t\t\tif stderrors.Is(err, errors.ErrNoServingTablet) {\n\t\t\t\t\tlog.Info(err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\trec.RecordError(fmt.Errorf(\"opts %+v, err: %w\", opts, err))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tschema, err := c.getSchemaFromTablets(ctx, ks.Keyspace.Name, tablets, opts)\n\t\t\tif err != nil {\n\t\t\t\trec.RecordError(err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Ignore keyspaces without schemas\n\t\t\tif schema == nil {\n\t\t\t\tlog.Info(\"No schemas for \" + ks.Keyspace.Name)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif len(schema.TableDefinitions) == 0 {\n\t\t\t\tlog.Info(\"No tables in schema for \" + ks.Keyspace.Name)\n\t\t\t\treturn","sourceCodeStart":1552,"sourceCodeEnd":1588,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/cluster/cluster.go#L1552-L1588","documentation":"In Cluster.GetSchema's per-keyspace fan-out, after FindTablets/getTabletsToQueryForSchemas fails, the error is recorded with the full GetSchema options attached for debugging. ErrNoServingTablet is deliberately logged at info and skipped; everything else is recorded as a real error.","triggerScenarios":"getSchemaForKeyspace fails for a keyspace with anything other than ErrNoServingTablet: FindTablets topo errors, or getTabletsToQueryForSchemas failures (tablet selection errors) — recorded as 'opts %+v, err: ...'.","commonSituations":"Tablet topology in flux during a reshard/reparent while schema is fetched; topo read errors mid-fan-out; invalid opts (bad keyspace/tablet filters) causing tablet selection to fail.","solutions":["Read the recorded message: opts identify which keyspace/tablet filter failed and the wrapped err gives the cause","Retry after topology stabilizes (reshard/reparent transient states)","Validate GetSchema opts (keyspace/tablet type filters) before issuing the request","If ErrNoServingTablet was the real cause, check whether the keyspace is expected to serve"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Go: validate GetSchema opts before calling\nif req.Keyspace == \"\" && len(req.Tablets) == 0 {\n\treturn fmt.Errorf(\"GetSchema opts must target a keyspace or tablets\")\n}","typeGuard":"func isNoServingTablet(err error) bool {\n\treturn errors.Is(err, errors.ErrNoServingTablet) // library skips this case\n}\nfunc isTabletSelectionErr(err error) bool {\n\treturn strings.Contains(err.Error(), \"opts +\")\n}","tryCatchPattern":"schema, err := c.GetSchema(ctx, req)\nif err != nil {\n\tif strings.Contains(err.Error(), \"opts +\") {\n\t\t// parse opts/cause from message; retry after topo stabilizes\n\t}\n\treturn err\n}","preventionTips":["Avoid schema fetches during reshard/reparent windows","Validate opts (keyspace/tablet filters) up front","Retry transient FindTablets failures","Confirm serving status of keyspaces before heavy schema queries"],"tags":["vtadmin","schema","topology","options"],"backgroundTag":"tablet-selection-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}