vitessio/vitess · error

failed to parse options column: %v

Error message

failed to parse options column: %v

What it means

When creating a vreplication controller, the workflow's `options` column (default `{}`) is unmarshaled into vtctldata.WorkflowOptions. If the stored text is not valid JSON or has the wrong shape, processWorkflowOptions returns `failed to parse options column: <err>`.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/controller.go:107

	tpCells          []string
	tpTabletTypesStr string
	tpOptions        discovery.TabletPickerOptions
}

// workflowTypeName returns the human-readable name for the workflow type
// (e.g. "OnlineDDL", "Reshard", "MoveTables").
func (ct *controller) workflowTypeName() string {
	return binlogdatapb.VReplicationWorkflowType(ct.workflowType).String()
}

func processWorkflowOptions(params map[string]string) (*vttablet.VReplicationConfig, error) {
	options, ok := params["options"]
	if !ok {
		options = "{}"
	}
	var workflowOptions vtctldata.WorkflowOptions
	if err := json.Unmarshal([]byte(options), &workflowOptions); err != nil {
		return nil, fmt.Errorf("failed to parse options column: %v", err)
	}
	workflowConfig, err := vttablet.NewVReplicationConfig(workflowOptions.Config)
	if err != nil {
		return nil, fmt.Errorf("failed to process config options: %v", err)
	}
	return workflowConfig, nil
}

// newController creates a new controller. Unless a stream is explicitly 'Stopped',
// this function launches a goroutine to perform continuous vreplication.
func newController(ctx context.Context, params map[string]string, dbClientFactory func() binlogplayer.DBClient, mysqld mysqlctl.MysqlDaemon, ts *topo.Server, cell string, blpStats *binlogplayer.Stats, vre *Engine, tpo discovery.TabletPickerOptions) (*controller, error) {
	if blpStats == nil {
		blpStats = binlogplayer.NewStats()
	}
	workflowConfig, err := processWorkflowOptions(params)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Inspect the `options` column for the workflow row in _vt.vreplication on the target primary and fix it to be valid JSON (usually `{}` if unused)
  2. Reset the options to the default `{}` for legacy workflows that never used options
  3. Restore the row from a backup if the value was corrupted, or recreate the workflow
  4. Verify the writing tool/version is compatible with the current Vitess WorkflowOptions format

Example fix

-- before
UPDATE _vt.vreplication SET options="{'config':'...'}" WHERE id=1; -- invalid JSON
-- after
UPDATE _vt.vreplication SET options='{"config":"..."}' WHERE id=1;
Defensive patterns

Strategy: validation

Validate before calling

// validate the options column is JSON before creating/reusing the workflow
var v map[string]any
if err := json.Unmarshal([]byte(optionsCol), &v); err != nil {
  return fmt.Errorf("options column is not valid JSON: %w", err)
}

Type guard

func isValidJSONObject(s string) bool {
  var m map[string]any
  return s == "" || (json.Unmarshal([]byte(s), &m) == nil && m != nil)
}

Try / catch

ct, err := newController(ctx, env, ...) 
if err != nil {
  if strings.Contains(err.Error(), "failed to parse options column") {
    // repair: set options='{}' for the workflow row, then re-enable the stream
  }
  return err
}

Prevention

When it happens

Trigger: The _vt.vreplication `options` column contains malformed JSON (truncated value, single quotes instead of double, non-JSON text), or a JSON value incompatible with the WorkflowOptions proto (e.g. a JSON array/string instead of an object).

Common situations: Manual edits to _vt.vreplication rows; workflows written by older Vitess versions storing a legacy options format; corruption from a partial update; external tools writing to the options column.

Understand the failure class

Related errors


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