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
- 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').
- Reset the stream to a known-good state via the workflow control commands (Workflow <name> Start/Stop).
- 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
- Never hand-edit the state column with arbitrary strings
- Use Workflow Start/Stop commands to change stream states
- Keep all tablets on the same Vitess version during rolling upgrades
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
- workflow has already been created, state is %s
- value out of range
- both atomic copy and partial mode cannot be specified for th
- invalid workflow
- multiple source keyspaces for a single workflow
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/d80daae6e1902d75.
Report an issue: GitHub.