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
- Update the row-producing code to emit exactly one value per table column, in the column order the sink was configured with
- Re-check the target table schema (column count) and reconcile it with the writer
- If using the Writer interface's SaveData, ensure the returned map contains an entry for every column
- 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
- Keep the row construction in one function tied to the table schema definition
- Write a unit test asserting row arity equals the table's column count
- When using SaveData, verify every column key is present in the returned map
- Update writers whenever the table schema migration adds/removes columns
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
- expected to write: , but written
- columns were empty
- failed to matched a field for SQL column
- failed to open database
- failed to prepare query
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)