JuliusBrussee/caveman · error

generic record %d: %w

Error message

generic record %d: %w

What it means

Thrown by the generic importer (shared/platform/importers/generic.go:75) when mapGeneric fails converting the i-th record (records are 1-based in the message) into a Span. The underlying cause is in the wrapped error: typically a source field mapped to a Span column has the wrong type or cannot be coerced. Like the JSONL importer, one bad record aborts the entire import.

Source

Thrown at shared/platform/importers/generic.go:75

func parseGeneric(data []byte, opts Options) ([]Span, error) {
	if err := validateGenericFieldMap(opts.FieldMap); err != nil {
		return nil, err
	}

	records, err := decodeGenericRecords(data)
	if err != nil {
		return nil, err
	}
	if len(records) == 0 {
		return []Span{}, nil
	}

	rows := make([]Span, 0, len(records))
	resolvedTargets := make(map[string]bool, len(opts.FieldMap))
	for i, rec := range records {
		sp, resolved, err := mapGeneric(rec, opts)
		if err != nil {
			return nil, fmt.Errorf("generic record %d: %w", i+1, err)
		}
		for target := range resolved {
			resolvedTargets[target] = true
		}
		rows = append(rows, sp)
	}
	for target, path := range opts.FieldMap {
		if !resolvedTargets[target] {
			return nil, fmt.Errorf("mapped source path %q for target %q was not found in any record", path, target)
		}
	}
	return rows, nil
}

func validateGenericFieldMap(fieldMap map[string]string) error {
	if len(fieldMap) == 0 {
		return fmt.Errorf("generic import requires a non-empty field map")
	}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Read the wrapped error - it names the failing field and record; inspect that record directly.
  2. Normalize the offending values at the source or in the FieldMap (map a different, consistently-typed source path).
  3. Drop or quarantine rows that cannot conform (in your own pre-processing), then re-import.
  4. For heterogeneous timestamps, pre-convert them to RFC3339 in the source file.
Defensive patterns

Strategy: try-catch

Validate before calling

// dry-run the first record through the same mapping before the batch
if len(records) > 0 {
    if _, _, err := mapGenericRecord(records[0], opts); err != nil {
        return fmt.Errorf("field map incompatible with sample record: %w", err)
    }
}

Try / catch

rows, err := importers.ImportGeneric(data, opts)
if err != nil {
    return fmt.Errorf("generic import failed at the record named in the error; nothing ingested: %w", err)
}

Prevention

When it happens

Trigger: Calling the generic import with a FieldMap and a dataset where, in record N, a mapped path resolves to a value incompatible with its target column - e.g. timestamp mapped to a plain string 'yesterday', or span_id mapped to a number where a string is required. The wrapped error says which field and why.

Common situations: CSV/JSON exports where a column's type drifts between rows (empty cell parsed as null, numbers formatted with thousands separators); timestamps in a non-supported format; schema evolution in the source system adding new formats; trailing summary rows in reports.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/24345fb51827fd1d. Report an issue: GitHub.