{"record":{"id":"eb4f5c72cdccba19","repo":"apache/beam","slug":"expected-to-write-v-but-written-v","errorCode":null,"errorMessage":"expected to write: %v, but written: %v","messagePattern":"expected to write: (.+?), but written: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/databaseio/writer.go","lineNumber":70,"sourceCode":"\t}\n\tw.binding = append(w.binding, row...)\n\treturn nil\n}\n\nfunc (w *writer) write(ctx context.Context, db *sql.DB) error {\n\tvalues := w.valueTemplateGenerator.generate(w.rowCount, w.columnCount)\n\tif len(values) == 0 {\n\t\tlog.Info(ctx, \"No value(s) to be written....\")\n\t\treturn nil\n\t}\n\tSQL := w.sqlTemplate + values\n\tresultSet, err := db.ExecContext(ctx, SQL, w.binding...)\n\tif err != nil {\n\t\treturn err\n\t}\n\taffected, _ := resultSet.RowsAffected()\n\tif int(affected) != w.rowCount {\n\t\treturn errors.Errorf(\"expected to write: %v, but written: %v\", w.rowCount, affected)\n\t}\n\tw.binding = []any{}\n\tw.rowCount = 0\n\treturn nil\n}\n\nfunc (w *writer) writeBatchIfNeeded(ctx context.Context, db *sql.DB) error {\n\tif w.rowCount >= w.batchSize {\n\t\treturn w.write(ctx, db)\n\t}\n\treturn nil\n}\n\nfunc (w *writer) writeIfNeeded(ctx context.Context, db *sql.DB) error {\n\tif w.rowCount >= 0 {\n\t\treturn w.write(ctx, db)\n\t}\n\treturn nil","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/databaseio/writer.go#L52-L88","documentation":"After executing the batched INSERT, writer.write compares database/sql's RowsAffected() result against the number of rows it attempted to write (w.rowCount). If the database reports a different number of affected rows, this error is thrown, because silently losing (or double-counting) rows would corrupt the pipeline's exactly-once expectations.","triggerScenarios":"Executing the multi-row INSERT where fewer (or more) rows are actually inserted than requested — e.g. some rows violate a constraint and the driver/dialect skips them, an INSERT IGNORE / ON DUPLICATE KEY style behavior suppresses rows, triggers alter the affected-row count, or the driver reports affected rows differently (some drivers return 0 or -1 for batch inserts, or rows with identical values are skipped by MySQL).","commonSituations":"MySQL with the default (non-CLIENT_FOUND_ROWS) behavior skipping duplicate rows in batch inserts; a table with triggers or ON CONFLICT DO NOTHING clauses; a driver whose RowsAffected is unreliable for multi-row statements; concurrent writers to the same table causing unexpected counts.","solutions":["Inspect the SQL table for constraints, unique keys, triggers, or ON CONFLICT/INSERT IGNORE clauses that suppress row inserts, and remove or account for them","Ensure the driver reports RowsAffected accurately for batch inserts (check driver docs/config, e.g. MySQL CLIENT_FOUND_ROWS flag)","Deduplicate or pre-validate incoming rows so every bound row is a genuine new insert","Retry the batch after clearing duplicates if the failure is transient contention"],"exampleFix":"// before\nINSERT IGNORE INTO users (id, name) VALUES ...  // duplicate rows silently skipped\n// after\nINSERT INTO users (id, name) VALUES ... ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name","handlingStrategy":"retry","validationCode":"// Before writing, check for rows that would be suppressed:\n// e.g. pre-query for existing unique keys\nfunc hasConflicts(ctx context.Context, db *sql.DB, table, keyCol string, keys []any) (bool, error) {\n    var n int\n    err := db.QueryRowContext(ctx,\n        fmt.Sprintf(\"SELECT COUNT(*) FROM %s WHERE %s IN (?%s)\", table, keyCol, strings.Repeat(\",?\", len(keys)-1)),\n        keys...).Scan(&n)\n    return n > 0, err\n}","typeGuard":null,"tryCatchPattern":"if err := w.write(ctx, db); err != nil {\n    if strings.Contains(err.Error(), \"expected to write\") {\n        // count mismatch: log rows, dedupe/fix conflicts, retry batch\n        return retryBatch(ctx, db, w)\n    }\n    return err\n}","preventionTips":["Avoid INSERT IGNORE / ON CONFLICT DO NOTHING unless you handle the count mismatch","Test batch inserts against the real driver; verify RowsAffected semantics","Remove or account for triggers that change affected-row counts","Deduplicate incoming rows before batching"],"tags":["go","sql","insert","rows-affected"],"backgroundTag":"database-write-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}