Budibase/budibase · error · Error
Failed to copy ${failed.length} row(s) after ${ROW_WRITE_RET
Error message
Failed to copy ${failed.length} row(s) after ${ROW_WRITE_RETRIES} attempts. What it means
A plain Error thrown by bulkInsertRows when, after the maximum ROW_WRITE_RETRIES attempts with exponential backoff, some rows still failed to write to the destination table during a row-copy/duplication operation. `failed.length` rows could not be persisted.
Source
Thrown at packages/server/src/sdk/workspace/resources/index.ts:662
let attempts = 0
while (pending.length && attempts < ROW_WRITE_RETRIES) {
attempts++
const response = (await destinationDb.bulkDocs(pending)) as Array<{
error?: unknown
}>
const failed: AnyDocument[] = []
response.forEach((result, idx) => {
if (result.error) {
failed.push(pending[idx])
}
})
if (!failed.length) {
break
}
if (attempts >= ROW_WRITE_RETRIES) {
throw new Error(
`Failed to copy ${failed.length} row(s) after ${ROW_WRITE_RETRIES} attempts.`
)
}
await delay(attempts * 250)
pending = failed
}
}
}
async function duplicateInternalTableRows(
tables: WithDocMetadata<Table>[],
destinationDb: ReturnType<typeof db.getDB>,
fromWorkspace: string,
toWorkspace: string
) {
if (!tables.length) {
returnView on GitHub (pinned to a81a902e9a)
Solutions
- Inspect the logged failed row batch to find the per-row write error and fix the offending data (schema mismatch, invalid types)
- Retry the copy operation once transient DB pressure has passed
- Reduce batch size or copy rows in smaller chunks to avoid timeouts/conflicts
- Verify CouchDB health (disk space, cluster status) before re-running large copies
Example fix
// before
await duplicateInternalTableRows(table) // bulk, all rows at once
// after
// catch and re-run only the failed subset, or pre-validate rows
try {
await duplicateInternalTableRows(table)
} catch (e) {
// inspect failed rows log, repair schema/data, retry
} Defensive patterns
Strategy: retry
Validate before calling
// pre-validate rows against the destination table schema before bulk insert const valid = rows.every(r => Object.keys(r).every(k => k in table.schema))
Type guard
function matchesSchema(row: Record<string, unknown>, table: Table): boolean return Object.keys(row).every(k => k in table.schema)
Try / catch
try {
await duplicateInternalTableRows(table)
} catch (e) {
if (/Failed to copy .* row\(s\)/.test(e.message)) {
// inspect failed-row logs, fix schema/data, then retry the operation
}
throw e
} Prevention
- Ensure destination table schema matches source rows before copying
- Copy in smaller batches to reduce write conflicts and timeouts
- Monitor CouchDB health/disk before large copies
- Keep failed-row output so partial failures can be repaired and re-run
When it happens
Trigger: bulkInsertRows repeatedly failing a subset of rows across all retry rounds — persistent CouchDB write errors, validation rejections (invalid row data for the target table schema), quota/disk issues, or rows conflicting with unique constraints in the destination table.
Common situations: Copying rows into a table whose schema changed (columns removed/renamed since the copy started); CouchDB instability or replication conflicts during large copies; destination DB read-only or out of disk; very large bulk copies timing out against a loaded cluster.
Related errors
- DB does not exist
- ${err.message}
- CouchDB error: ${err.message}
- Unable to get bulk documents: ${missingIds}
- Unable to remove doc without a valid _id and _rev.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/3b16e883ccc65ce6.
Report an issue: GitHub.