cockroachdb/cockroach · error

failed parsing datum string as

Error message

failed parsing datum string as 

What it means

While consuming statistics.json from a statement bundle (placeholder machinery used by statement-bundle editing), each histogram bucket's upper_bound string is parsed with rowenc.ParseDatumStringAs against the type taken from histo_col_type. A parse failure panics with 'failed parsing datum string as <colType> <err>', aborting the whole command — the error is not returned gracefully.

Source

Thrown at pkg/cli/statement_bundle.go:435

			buckets := stat["histo_buckets"].([]interface{})
			// addedNonExistent tracks whether we included at least one
			// "previous" datum which - according to the histograms - is not
			// present in the table.
			var addedNonExistent bool
			var maxUpperBound tree.Datum
			for _, b := range buckets {
				bucket := b.(map[string]interface{})
				numRange := bucket["num_range"].(float64)
				key := bucketKey{
					NumEq:         bucket["num_eq"].(float64),
					NumRange:      numRange,
					DistinctRange: bucket["distinct_range"].(float64),
				}
				upperBound := bucket["upper_bound"].(string)
				bucketMap[key] = []string{upperBound}
				datum, err := rowenc.ParseDatumStringAs(ctx, colType, upperBound, &evalCtx, nil /* semaCtx */)
				if err != nil {
					panic("failed parsing datum string as " + colType.String() + " " + err.Error())
				}
				if maxUpperBound == nil {
					maxUpperBound = datum
				} else if cmp, err := maxUpperBound.Compare(ctx, &evalCtx, datum); err != nil {
					panic(err)
				} else if cmp < 0 {
					maxUpperBound = datum
				}
				// If we have any datums within the bucket (i.e. not equal to
				// the upper bound), we always attempt to add a "previous" to
				// the upper bound datum.
				addPrevious := numRange > 0
				if numRange == 0 && !addedNonExistent {
					// If our bucket says that there are no values present in
					// the table between the current upper bound and the upper
					// bound of the previous histogram bucket, then we only
					// attempt to add the "previous" non-existent datum if we
					// haven't done so already (this is to avoid the redundant

View on GitHub (pinned to 8812064a01)

Solutions

  1. Regenerate the statement bundle on the cluster that ran the query, then retry
  2. Open statistics.json and compare histo_col_type with the actual upper_bound strings for the failing column (the panic message names the type and underlying error)
  3. Process the bundle with the cockroach binary version matching the cluster that produced it
  4. If the JSON is valid and from a supported version, report a bug — parsing should error, not panic

Example fix

// before (statement_bundle.go)
if err != nil {
  panic('failed parsing datum string as ' + colType.String() + ' ' + err.Error())
}

// after: propagate a descriptive error instead of panicking
if err != nil {
  return nil, nil, errors.Wrapf(err, 'parsing upper_bound %q for column %s as %s', upperBound, fqColName, colType.String())
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: An upper_bound whose string encoding doesn't round-trip through histo_col_type: statistics produced by a different CockroachDB version with changed datum formatting, hand-edited or foreign statistics.json files, or a type whose string form ParseDatumStringAs rejects.

Common situations: Applying/editing a statement bundle captured on an older or newer cluster; statistics.json copied between clusters; user-modified histogram buckets; rarely, encoding changes for exotic types (arrays, certain collations) across versions.

Related errors


AI-assisted analysis of cockroachdb/cockroach@8812064a01 (2026-08-15). Data as JSON: /api/errors/632433e0d10b47f6. Report an issue: GitHub.