{"record":{"id":"b1a77ac6c7bbf2cf","repo":"vitessio/vitess","slug":"tablet-alias-is-nil","errorCode":null,"errorMessage":"tablet alias is nil","messagePattern":"tablet alias is nil","errorType":"error_code","errorClass":"ErrTabletAliasNil","httpStatus":null,"severity":"error","filePath":"go/vt/vtorc/inst/tablet_dao.go","lineNumber":37,"sourceCode":"import (\n\t\"context\"\n\t\"errors\"\n\n\t\"google.golang.org/protobuf/encoding/prototext\"\n\n\t\"vitess.io/vitess/go/protoutil\"\n\t\"vitess.io/vitess/go/vt/external/golib/sqlutils\"\n\treplicationdatapb \"vitess.io/vitess/go/vt/proto/replicationdata\"\n\ttopodatapb \"vitess.io/vitess/go/vt/proto/topodata\"\n\t\"vitess.io/vitess/go/vt/topo\"\n\t\"vitess.io/vitess/go/vt/topo/topoproto\"\n\t\"vitess.io/vitess/go/vt/vtorc/db\"\n\t\"vitess.io/vitess/go/vt/vttablet/tmclient\"\n)\n\n// ErrTabletAliasNil is a fixed error message.\nvar (\n\tErrTabletAliasNil = errors.New(\"tablet alias is nil\")\n\ttmc               tmclient.TabletManagerClient\n)\n\n// InitializeTMC initializes the tablet manager client to use for all VTOrc RPC calls.\nfunc InitializeTMC() tmclient.TabletManagerClient {\n\ttmc = tmclient.NewTabletManagerClient()\n\treturn tmc\n}\n\n// fullStatus gets the full status of the MySQL running in vttablet.\nfunc fullStatus(tablet *topodatapb.Tablet) (*replicationdatapb.FullStatus, error) {\n\ttmcCtx, tmcCancel := context.WithTimeout(context.Background(), topo.RemoteOperationTimeout)\n\tdefer tmcCancel()\n\treturn tmc.FullStatus(tmcCtx, tablet)\n}\n\n// ReadTablet reads the vitess tablet record.\nfunc ReadTablet(tabletAlias *topodatapb.TabletAlias) (*topodatapb.Tablet, error) {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtorc/inst/tablet_dao.go#L19-L55","documentation":"ErrTabletAliasNil is the sentinel error returned by ReadTablet (and surfaced by refreshTablets) when a nil tablet alias is passed. The alias is the primary key for looking up a tablet, so a nil value is rejected immediately.","triggerScenarios":"Calling ReadTablet(ctx, nil) — commonly when an upstream topo read or shard-primary lookup returned a nil alias without a corresponding error.","commonSituations":"Shard records with an empty primary alias (no primary elected yet) being passed to ReadTablet; bugs in tablet enumeration loops; partially loaded topo data.","solutions":["Guard the call site with a nil check on the alias before calling ReadTablet.","Fix the upstream lookup to return an error instead of a nil alias with nil error.","Handle the not-yet-elected-primary case explicitly: skip tablets whose shard has no primary alias."],"exampleFix":"// before\nt, err := inst.ReadTablet(ctx, alias)\n// after\nif alias == nil {\n    return nil, inst.ErrTabletAliasNil\n}\nt, err := inst.ReadTablet(ctx, alias)","handlingStrategy":"validation","validationCode":"if alias == nil {\n    return nil, inst.ErrTabletAliasNil\n}","typeGuard":"func hasPrimaryAlias(shard *topo.ShardInfo) bool {\n    return shard.GetPrimaryAlias() != nil\n}","tryCatchPattern":"t, err := inst.ReadTablet(ctx, alias)\nif errors.Is(err, inst.ErrTabletAliasNil) {\n    log.Warn(\"tablet read skipped: nil alias (shard may have no primary)\")\n    return nil\n} else if err != nil { return err }","preventionTips":["Check shard.GetPrimaryAlias() for nil before primary-dependent reads.","Make upstream lookups return errors alongside nil results instead of silent nils.","Validate aliases (non-nil, non-empty cell/uid) at API boundaries."],"tags":["vtorc","tablet","nil-argument","validation"],"backgroundTag":"nil-argument","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}