{"record":{"id":"75e6eb549015afc8","repo":"vitessio/vitess","slug":"readtopologyinstance-will-not-act-on-empty-tablet","errorCode":null,"errorMessage":"ReadTopologyInstance will not act on empty tablet alias","messagePattern":"ReadTopologyInstance will not act on empty tablet alias","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtorc/inst/instance_dao.go","lineNumber":181,"sourceCode":"// - timing information can be collected for the stages performed.\nfunc ReadTopologyInstanceBufferable(tabletAlias *topodatapb.TabletAlias, latency *stopwatch.NamedStopwatch) (inst *Instance, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = logReadTopologyInstanceError(tabletAlias, \"Unexpected, aborting\", tb.Errorf(\"%+v\", r))\n\t\t}\n\t}()\n\n\tvar tablet *topodatapb.Tablet\n\tvar fs *replicationdatapb.FullStatus\n\treadingStartTime := time.Now()\n\tstalledDisk := false\n\tinstance := NewInstance()\n\tinstanceFound := false\n\tpartialSuccess := false\n\terrorChan := make(chan error, 32)\n\n\tif tabletAlias == nil {\n\t\treturn instance, errors.New(\"ReadTopologyInstance will not act on empty tablet alias\")\n\t}\n\n\tlastAttemptedCheckTimer := time.AfterFunc(time.Second, func() {\n\t\tgo func() {\n\t\t\t_ = UpdateInstanceLastAttemptedCheck(tabletAlias)\n\t\t}()\n\t})\n\n\tlatency.Start(\"instance\")\n\n\ttablet, err = ReadTablet(tabletAlias)\n\tif err != nil {\n\t\tgoto Cleanup\n\t}\n\tif tablet == nil {\n\t\t// This can happen because Orc rediscovers instances by alt hostnames,\n\t\t// lit localhost, ip, etc.\n\t\t// TODO(sougou): disable this ability.","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtorc/inst/instance_dao.go#L163-L199","documentation":"ReadTopologyInstanceBufferable validates its input before doing any work and refuses to proceed when the tabletAlias pointer is nil. This is a defensive guard because a nil alias cannot identify a tablet to discover. Callers must always pass a valid *topodatapb.TabletAlias.","triggerScenarios":"Calling ReadTopologyInstanceBufferable (directly or via DiscoverInstance) with tabletAlias == nil, typically when an upstream lookup (e.g., topo server read) returned nil without an error being propagated.","commonSituations":"A discovery loop iterates over results from a partially failed topo read that yields nil aliases; a bug in code constructing a TabletAlias; reading a tablet from a keyspace/shard where the primary record is empty.","solutions":["Check the caller that produced the nil alias and fix the upstream lookup so it either returns a valid alias or an error.","Guard the call site: skip or log when the alias is nil before invoking discovery.","Run vtorc with debug logging to find which tablet source produced the nil alias."],"exampleFix":"// before\ninst, err := inst.ReadTopologyInstanceBufferable(ctx, nil, hint)\n// after\nif alias == nil {\n    return errors.New(\"cannot discover: tablet alias is nil\")\n}\ninst, err := inst.ReadTopologyInstanceBufferable(ctx, alias, hint)","handlingStrategy":"validation","validationCode":"if tabletAlias == nil {\n    return errors.New(\"cannot discover: tablet alias is nil\")\n}","typeGuard":"func validAlias(a *topodatapb.TabletAlias) bool {\n    return a != nil && a.Uid != 0 && a.Cell != \"\"\n}","tryCatchPattern":"inst, err := inst.ReadTopologyInstanceBufferable(ctx, alias, hint)\nif err != nil && strings.Contains(err.Error(), \"empty tablet alias\") {\n    log.Warn(\"skipped discovery: nil alias from upstream lookup\")\n    return nil\n} else if err != nil { return err }","preventionTips":["Always check topo read results for nil aliases before passing them downstream.","Return errors (not nil,nil) from helper functions that fetch tablet aliases.","Log upstream lookups that yield nil aliases to find the producing code path."],"tags":["vtorc","topology-discovery","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"}