vitessio/vitess · error

failed parsing primary_term_start_time %s: %w

Error message

failed parsing primary_term_start_time %s: %w

What it means

Thrown by parseTablet when the tablet record carries a primary_term_start_time string that fails to parse as RFC3339 (time.Parse(time.RFC3339, ...)). Primary term start time marks when the current PRIMARY tablet's term began, and vtadmin expects it serialized in RFC3339 (e.g. 2023-01-02T15:04:05Z).

Source

Thrown at go/vt/vtadmin/cluster/cluster.go:340

		return nil, err
	}

	tablet.State = vtadminproto.ParseTabletServingState(servingStateStr)

	topotablet.Alias, err = topoproto.ParseTabletAlias(aliasStr)
	if err != nil {
		return nil, fmt.Errorf("failed to parse tablet_alias %s: %w", aliasStr, err)
	}

	if topotablet.Alias.Cell != cell {
		// (TODO:@amason) ???
		log.Warn(fmt.Sprintf("tablet cell %s does not match alias %s. ignoring for now", cell, topoproto.TabletAliasString(topotablet.Alias)))
	}

	if mtstStr != "" {
		timeTime, err := time.Parse(time.RFC3339, mtstStr)
		if err != nil {
			return nil, fmt.Errorf("failed parsing primary_term_start_time %s: %w", mtstStr, err)
		}

		topotablet.PrimaryTermStartTime = protoutil.TimeToProto(timeTime)
	}

	if c.TabletFQDNTmpl != nil {
		tablet.FQDN, err = textutil.ExecuteTemplate(c.TabletFQDNTmpl, tablet)
		if err != nil {
			return nil, fmt.Errorf("failed to execute tablet FQDN template for %+v: %w", tablet, err)
		}
	}

	return tablet, nil
}

// ApplySchema applies a schema to the given keyspace in this cluster.
func (c *Cluster) ApplySchema(ctx context.Context, req *vtctldatapb.ApplySchemaRequest) (*vtctldatapb.ApplySchemaResponse, error) {
	span, ctx := trace.NewSpan(ctx, "Cluster.ApplySchema")

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the primary_term_start_time value in the error message; convert the source to RFC3339 (e.g. `time.Unix(ts,0).UTC().Format(time.RFC3339)`).
  2. If the value came from custom scripts/tooling, fix them to emit RFC3339 timestamps.
  3. Upgrade/downgrade vtctld and vttablets so all components serialize times consistently (vitess protoutil conventions).
  4. If the field should be unset, clear it so the empty-string guard (mtstStr != "") skips parsing.

Example fix

// before
mtstStr = "1672674245" // unix seconds, not RFC3339
// after
mtstStr = "2023-01-02T15:04:05Z" // time.Unix(1672674245,0).UTC().Format(time.RFC3339)
Defensive patterns

Strategy: validation

Validate before calling

mtstStr := "2023-01-02T15:04:05Z"
if _, err := time.Parse(time.RFC3339, mtstStr); err != nil {
	return fmt.Errorf("primary_term_start_time %q is not RFC3339", mtstStr)
}

Type guard

func isRFC3339(s string) bool {
	_, err := time.Parse(time.RFC3339, s)
	return err == nil
}

Prevention

When it happens

Trigger: Discovering tablets via parseTablets where the source record's primary_term_start_time field is non-empty but not RFC3339-formatted — e.g. a unix timestamp integer, a partial datetime, or locale-formatted time.

Common situations: Custom tooling or scripts writing tablet records with unix-epoch timestamps instead of RFC3339 strings; vttablet/vtctld version mismatch producing a different time serialization; hand-crafted test topo data.

Related errors


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