vitessio/vitess · error

failed to parse workflow_sub_type column: %v

Error message

failed to parse workflow_sub_type column: %v

What it means

Returned by the binlog player when the workflow_sub_type column value from the vreplication metadata row cannot be parsed, wrapping the underlying conversion error.

Source

Thrown at go/vt/binlog/binlogplayer/binlog_player.go:607

	maxReplicationLag, err := vrRow.ToInt64("max_replication_lag")
	if err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse max_replication_lag column: %v", err)
	}
	startPos, err := DecodePosition(vrRow.AsString("pos", ""))
	if err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse pos column: %v", err)
	}
	stopPos, err := replication.DecodePosition(vrRow.AsString("stop_pos", ""))
	if err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse stop_pos column: %v", err)
	}
	workflowType, err := vrRow.ToInt32("workflow_type")
	if err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse workflow_type column: %v", err)
	}
	workflowSubType, err := vrRow.ToInt32("workflow_sub_type")
	if err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse workflow_sub_type column: %v", err)
	}
	deferSecondaryKeys, err := vrRow.ToBool("defer_secondary_keys")
	if err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse defer_secondary_keys column: %v", err)
	}
	options := vrRow.AsString("options", "{}")
	var workflowOptions vtctldata.WorkflowOptions
	if err := json.Unmarshal([]byte(options), &workflowOptions); err != nil {
		return VRSettings{}, fmt.Errorf("failed to parse options column: %v", err)
	}
	return VRSettings{
		StartPos:           startPos,
		StopPos:            stopPos,
		MaxTPS:             maxTPS,
		MaxReplicationLag:  maxReplicationLag,
		State:              binlogdatapb.VReplicationWorkflowState(binlogdatapb.VReplicationWorkflowState_value[vrRow.AsString("state", "")]),
		WorkflowType:       binlogdatapb.VReplicationWorkflowType(workflowType),
		WorkflowName:       vrRow.AsString("workflow", ""),

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the stored value: `select uid, workflow_sub_type from _vt.vreplication where uid=<id>`.
  2. Set it to a valid vtctldata.WorkflowSubType value (0 = None is safe for simple workflows).
  3. Upgrade/restore the canonical _vt schema if it drifted between Vitess versions.
  4. Re-create the workflow if metadata is unrecoverable.

Example fix

// before
update _vt.vreplication set workflow_sub_type='none' where uid=1;
// after
update _vt.vreplication set workflow_sub_type=0 where uid=1;
Defensive patterns

Strategy: validation

Validate before calling

qr, _ := dbClient.ExecuteFetch(fmt.Sprintf("SELECT workflow_sub_type FROM _vt.vreplication WHERE uid=%d", uid), 1)
if len(qr.Rows) == 1 {
	v := qr.Named().Row().AsString("workflow_sub_type", "")
	if _, err := strconv.ParseInt(v, 10, 32); err != nil {
		return fmt.Errorf("workflow_sub_type %q invalid; set a valid WorkflowSubType value (0 = None)", v)
	}
}

Type guard

func isValidWorkflowSubType(s string) bool {
	n, err := strconv.ParseInt(s, 10, 32)
	return err == nil && n >= 0
}

Try / catch

settings, err := binlogplayer.ReadVRSettings(dbClient, uid)
if err != nil && strings.Contains(err.Error(), "failed to parse workflow_sub_type") {
	_, _ = dbClient.ExecuteFetch(fmt.Sprintf("UPDATE _vt.vreplication SET workflow_sub_type=0 WHERE uid=%d", uid), 0)
	settings, err = binlogplayer.ReadVRSettings(dbClient, uid)
}

Prevention

When it happens

Trigger: vrRow.ToInt32("workflow_sub_type") fails: NULL or non-numeric content in the column, schema drift from restores, or manual row writes omitting a valid sub-type.

Common situations: Older backups of _vt.vreplication lacking/with different sub-type data; manual inserts; interrupted updates.

Understand the failure class

Related errors


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