apache/beam · error

expected row values, but had

Error message

expected %v row values, but had: %v

What it means

The databaseio writer batches row values into a single multi-row INSERT statement; every row must supply exactly one value per column of the target table (w.columnCount, derived from the table metadata). writer.add validates this before appending to the binding slice, because a short or long row would misalign every placeholder in the generated SQL. This error means the row slice handed to the writer has the wrong arity.

Solutions

  1. Update the row-producing code to emit exactly one value per table column, in the column order the sink was configured with
  2. Re-check the target table schema (column count) and reconcile it with the writer
  3. If using the Writer interface's SaveData, ensure the returned map contains an entry for every column
  4. Add a unit test asserting len(row) == expected column count before write

Example fix

// before
row := []any{u.ID, u.Name} // table has 3 columns
// after
row := []any{u.ID, u.Name, u.Email}
Defensive patterns

Strategy: validation

Validate before calling

func validateRowLength(row []any, columnCount int) error {
    if len(row) != columnCount {
        return fmt.Errorf("row has %d values, table has %d columns", len(row), columnCount)
    }
    return nil
}

Try / catch

if err := w.add(row); err != nil {
    return fmt.Errorf("databaseio add failed for row %d: %w", i, err)
}

Prevention

When it happens

Trigger: A DoFn (ProcessElement) producing rows for databaseio.Write emits a []any whose length differs from the number of columns in the target table — typically when SaveData or the row-construction code doesn't return one value per column, or the table schema was altered after the pipeline was written.

Common situations: Adding/dropping a table column without updating the writer DoFn; building the row conditionally so some elements are omitted; using SaveData to serialize a struct where an embedded/optional field is skipped; copying an example writer for a different table shape.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/c9f862bc1645b7e6. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/io/databaseio/writer.go:51

	SaveData() (map[string]any, error)
}

type writer struct {
	batchSize              int
	table                  string
	sqlTemplate            string
	valueTemplateGenerator *valueTemplateGenerator
	binding                []any
	columnCount            int
	rowCount               int
	totalCount             int
}

func (w *writer) add(row []any) error {
	w.rowCount++
	w.totalCount++
	if len(row) != w.columnCount {
		return errors.Errorf("expected %v row values, but had: %v", w.columnCount, len(row))
	}
	w.binding = append(w.binding, row...)
	return nil
}

func (w *writer) write(ctx context.Context, db *sql.DB) error {
	values := w.valueTemplateGenerator.generate(w.rowCount, w.columnCount)
	if len(values) == 0 {
		log.Info(ctx, "No value(s) to be written....")
		return nil
	}
	SQL := w.sqlTemplate + values
	resultSet, err := db.ExecContext(ctx, SQL, w.binding...)
	if err != nil {
		return err
	}
	affected, _ := resultSet.RowsAffected()
	if int(affected) != w.rowCount {

View on GitHub (pinned to 12126d8942)