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 redundantView on GitHub (pinned to 8812064a01)
Solutions
- Regenerate the statement bundle on the cluster that ran the query, then retry
- 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)
- Process the bundle with the cockroach binary version matching the cluster that produced it
- 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
- Process statement bundles with the binary version that produced them
- Never hand-edit histogram upper_bound values in statistics.json
- Regenerate bundles on-cluster instead of reusing old statistics.json across versions
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
- error while processing file %s
- could not parse query (expected PKG.TEST): %s
- cannot set both COCKROACH_FORCE_DEV_VERSION and COCKROACH_TE
- cannot have two files with the same basename in DISTDIR_FILE
- invalid trusted proxy CIDRs
AI-assisted analysis of cockroachdb/cockroach@8812064a01 (2026-08-15).
Data as JSON: /api/errors/632433e0d10b47f6.
Report an issue: GitHub.