vitessio/vitess · error
controller could not be initialized for stream %+v on tablet
Error message
controller could not be initialized for stream %+v on tablet %v
What it means
addController wraps a failure from newController (which builds a vdiff controller from a _vt.vdiff row) with this message. newController itself returns the underlying cause; this wrapper adds the stream row and tablet alias so operators know which vdiff and tablet failed during create/resume/retry.
Source
Thrown at go/vt/vttablet/tabletmanager/vdiff/engine.go:217
}
if err := vde.openLocked(ctx); err == nil {
log.Info("VDiff engine: opened successfully")
// Don't invoke cancelRetry because openLocked
// will hold on to this context for later cancellation.
vde.cancelRetry = nil
vde.mu.Unlock()
return
}
vde.mu.Unlock()
}
}
// addController creates a new controller using the given vdiff record and adds it to the engine.
// You must already have the main engine mutex (mu) locked before calling this.
func (vde *Engine) addController(row sqltypes.RowNamedValues, options *tabletmanagerdata.VDiffOptions) error {
ct, err := newController(row, vde.dbClientFactoryDba, vde.ts, vde, options)
if err != nil {
return fmt.Errorf("controller could not be initialized for stream %+v on tablet %v",
row, vde.thisTablet.Alias)
}
vde.controllers[ct.id] = ct
globalStats.mu.Lock()
defer globalStats.mu.Unlock()
globalStats.controllers[ct.id] = ct
controllerCtx, cancel := context.WithCancel(vde.ctx)
ct.cancel = cancel
go ct.run(controllerCtx)
return nil
}
func (vde *Engine) initControllers(qr *sqltypes.Result) error {
if qr == nil || len(qr.Rows) == 0 {
return nil
}
for _, row := range qr.Named().Rows {View on GitHub (pinned to 01a25a7d17)
Solutions
- Look at the wrapped inner error from newController in the same log chain — it names the real cause.
- Validate the offending _vt.vdiff row (source, target, options columns) and delete/recreate the vdiff.
- Verify topo connectivity and that the source/target tablets exist: vtctldclient GetTablets.
- If resume keeps failing, delete the vdiff record and start a fresh VDiff Create.
Example fix
// before (resume of corrupt row) vtctldclient vdiff --keyspace ks --workflow wf resume // -> controller could not be initialized ... // after vtctldclient vdiff --keyspace ks --workflow wf delete all vtctldclient vdiff --keyspace ks --workflow wf create
Defensive patterns
Strategy: try-catch
Validate before calling
// before resume/create, check topo and row sanity
err := topoCheck(keyspace) // tablets exist
row, _ := db.Query("SELECT options FROM _vt.vdiff WHERE vdiff_uuid=?", uuid)
json.Valid(row["options"]) // options column must be valid JSON Try / catch
err := vde.PerformVDiffAction(ctx, req)
if err != nil && strings.Contains(err.Error(), "controller could not be initialized") {
log.Error(err.Error()) // inspect wrapped cause
// fall back: delete all + recreate vdiff
} Prevention
- Read the wrapped newController error for the root cause before retrying.
- Keep topo healthy; verify tablets exist before resuming vdiffs.
- Don't hand-edit _vt.vdiff rows; recreate the vdiff instead.
- Avoid resuming vdiffs across version upgrades without recreating them.
When it happens
Trigger: handleCreateResumeAction or initControllers/retryVDiffs calling addController where the vdiff row has invalid/missing fields (bad JSON in options, invalid position, malformed source/target), or required tablet/topology lookups inside newController fail.
Common situations: Corrupt _vt.vdiff row after a manual edit; keyspace/tablet missing from topo during resume after a topology change; a vdiff created against a source keyspace that no longer exists; incompatible options JSON written by an older version.
Related errors
- not allowed: deny-all security-policy enforced
- not allowed: read-only security-policy enforced
- invalid choice for enum
- value must be either a float64 (interpreted as seconds) or a
- flagutil: NewOptionalFlag requires a non-nil parse function
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/d934d07a98d6fbc3.
Report an issue: GitHub.