vitessio/vitess · error

stream %d for %v.%v is not in Running state: %v

Error message

stream %d for %v.%v is not in Running state: %v

What it means

During vindex externalization validation, Wrangler checks each vreplication stream on the target shards. When the vindex has no owner (or StopAfterCopy is false), all streams must be in Running state; any other state (Copying, Error, Stopped) fails validation.

Source

Thrown at go/vt/wrangler/materializer.go:887

			id, err := row[0].ToCastInt64()
			if err != nil {
				return err
			}
			state := binlogdatapb.VReplicationWorkflowState(binlogdatapb.VReplicationWorkflowState_value[row[1].ToString()])
			message := row[2].ToString()
			var bls binlogdatapb.BinlogSource
			sourceBytes, err := row[3].ToBytes()
			if err != nil {
				return err
			}
			if err := prototext.Unmarshal(sourceBytes, &bls); err != nil {
				return err
			}
			if sourceVindex.Owner == "" || !bls.StopAfterCopy {
				// If there's no owner or we've requested that the workflow NOT be stopped
				// after the copy phase completes, then all streams need to be running.
				if state != binlogdatapb.VReplicationWorkflowState_Running {
					return fmt.Errorf("stream %d for %v.%v is not in Running state: %v", id, targetShard.Keyspace(), targetShard.ShardName(), state)
				}
			} else {
				// If there is an owner, all streams need to be stopped after copy.
				if state != binlogdatapb.VReplicationWorkflowState_Stopped || !strings.Contains(message, "Stopped after copy") {
					return fmt.Errorf("stream %d for %v.%v is not in Stopped after copy state: %v, %v", id, targetShard.Keyspace(), targetShard.ShardName(), state, message)
				}
			}
		}
		return nil
	})
	if err != nil {
		return err
	}

	if sourceVindex.Owner != "" {
		// If there is an owner, we have to delete the streams.
		err := forAllTargets(func(targetShard *topo.ShardInfo) error {
			targetPrimary, err := wr.ts.GetTablet(ctx, targetShard.PrimaryAlias)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check stream status with vtctldclient Workflow --workflow <name> Show and wait for all streams to be Running.
  2. If a stream is in Error, fix the underlying cause (e.g. MySQL error on the target) and restart the workflow.
  3. Restart stopped streams with the workflow Start command, then retry ExternalizeVindex.
  4. If the vindex has an owner and should stop after copy, ensure the message contains 'Stopped after copy' — otherwise this branch does not apply.

Example fix

// before: externalize while copying
vtctldclient ExternalizeVindex commerce.corder_vdx
// after: wait until streams are Running
vtctldclient Workflow --workflow corder_vdx_vdx Show  # all Running
vtctldclient ExternalizeVindex commerce.corder_vdx
Defensive patterns

Strategy: validation

Validate before calling

shs, _ := wr.ts.GetVReplicationWorkflow(ctx, "corder_vdx_vdx")
for _, s := range shs.Streams {
  if s.State != binlogdatapb.VReplicationWorkflowState_Running {
    return fmt.Errorf("stream %d not running yet: %s", s.Id, s.State)
  }
}

Try / catch

if err := wr.ExternalizeVindex(ctx, name); err != nil {
  if strings.Contains(err.Error(), "is not in Running state") {
    // poll workflow status with backoff until all streams Running, then retry
  }
}

Prevention

When it happens

Trigger: ExternalizeVindex invoked while the backfill/lookup vreplication streams are still copying, in error, or were manually stopped, for an ownerless vindex.

Common situations: Running ExternalizeVindex before the copy phase completed; a stream failed mid-backfill; someone manually stopped the workflow via Workflow...Stop before externalizing an ownerless vindex.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/608457a0711cb136. Report an issue: GitHub.