vitessio/vitess · error

invalid state for stream %s of workflow %s.%s

Error message

invalid state for stream %s of workflow %s.%s

What it means

When aggregating a workflow's status across all its shard streams, each stream's state string is mapped to the VReplicationWorkflowState enum. If the stored state string is not a valid enum value, the status computation cannot proceed and returns this error naming the stream and workflow.

Source

Thrown at go/vt/vtctl/workflow/server.go:3677

		AutoStart:                 req.AutoStart,
		NoRoutingRules:            req.NoRoutingRules,
	}
	return s.moveTablesCreate(ctx, moveTablesCreateRequest, binlogdatapb.VReplicationWorkflowType_Migrate)
}

// getWorkflowStatus gets the overall status of the workflow by checking the status of all the streams. If all streams are not
// in the same state, it returns the unknown state.
func (s *Server) getWorkflowStatus(ctx context.Context, keyspace string, workflow string) (binlogdatapb.VReplicationWorkflowState, error) {
	workflowStatus := binlogdatapb.VReplicationWorkflowState_Unknown
	wf, err := s.GetWorkflow(ctx, keyspace, workflow, false, nil)
	if err != nil {
		return workflowStatus, err
	}
	for _, shardStream := range wf.GetShardStreams() {
		for _, stream := range shardStream.GetStreams() {
			state, ok := binlogdatapb.VReplicationWorkflowState_value[stream.State]
			if !ok {
				return workflowStatus, fmt.Errorf("invalid state for stream %s of workflow %s.%s", stream.State, keyspace, workflow)
			}
			currentStatus := binlogdatapb.VReplicationWorkflowState(state)
			if workflowStatus != binlogdatapb.VReplicationWorkflowState_Unknown && currentStatus != workflowStatus {
				return binlogdatapb.VReplicationWorkflowState_Unknown, nil
			}
			workflowStatus = currentStatus
		}
	}
	return workflowStatus, nil
}

// WorkflowMirrorTraffic mirrors traffic from the source keyspace to the target keyspace.
func (s *Server) WorkflowMirrorTraffic(ctx context.Context, req *vtctldatapb.WorkflowMirrorTrafficRequest) (*vtctldatapb.WorkflowMirrorTrafficResponse, error) {
	ts, startState, err := s.getWorkflowState(ctx, req.Keyspace, req.Workflow)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Inspect the stream's state: SELECT state FROM _vt.vreplication WHERE workflow='<wf>'; and correct it to a valid value (e.g. 'Running', 'Stopped', 'Error').
  2. Reset the stream to a known-good state via the workflow control commands (Workflow <name> Start/Stop).
  3. Ensure all tablets run compatible Vitess versions during upgrades.

Example fix

-- before
UPDATE _vt.vreplication SET state='runing' WHERE id=<id>;
-- after
UPDATE _vt.vreplication SET state='Running' WHERE id=<id>;
Defensive patterns

Strategy: validation

Validate before calling

-- Verify all stream states are valid enum values
SELECT id, state FROM _vt.vreplication WHERE state NOT IN ('Unknown','Running','Stopping','Stopped','Error','Updating','Copying');

Try / catch

wf, err := client.GetWorkflows(ctx, keyspace)
if err != nil && strings.Contains(err.Error(), "invalid state for stream") {
    // fix the invalid state value on the named shard, then re-query
}

Prevention

When it happens

Trigger: Calling WorkflowStatus (or any status aggregation, e.g. via Workflow server APIs / vtctld GetWorkflows) while a _vt.vreplication row holds a state string that is not one of the defined VReplicationWorkflowState values.

Common situations: Direct manual UPDATE of the state column with a typo'd value; state strings written by an incompatible (older/newer) Vitess version; corrupted vreplication rows from partial writes.

Related errors


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