{"record":{"id":"3b16e883ccc65ce6","repo":"Budibase/budibase","slug":"failed-to-copy-failed-length-row-s-after-row","errorCode":null,"errorMessage":"Failed to copy ${failed.length} row(s) after ${ROW_WRITE_RETRIES} attempts.","messagePattern":"Failed to copy (.+?) row\\(s\\) after (.+?) attempts\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/resources/index.ts","lineNumber":662,"sourceCode":"    let attempts = 0\n    while (pending.length && attempts < ROW_WRITE_RETRIES) {\n      attempts++\n      const response = (await destinationDb.bulkDocs(pending)) as Array<{\n        error?: unknown\n      }>\n      const failed: AnyDocument[] = []\n      response.forEach((result, idx) => {\n        if (result.error) {\n          failed.push(pending[idx])\n        }\n      })\n\n      if (!failed.length) {\n        break\n      }\n\n      if (attempts >= ROW_WRITE_RETRIES) {\n        throw new Error(\n          `Failed to copy ${failed.length} row(s) after ${ROW_WRITE_RETRIES} attempts.`\n        )\n      }\n\n      await delay(attempts * 250)\n      pending = failed\n    }\n  }\n}\n\nasync function duplicateInternalTableRows(\n  tables: WithDocMetadata<Table>[],\n  destinationDb: ReturnType<typeof db.getDB>,\n  fromWorkspace: string,\n  toWorkspace: string\n) {\n  if (!tables.length) {\n    return","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/resources/index.ts#L644-L680","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait duplicateInternalTableRows(table) // bulk, all rows at once\n// after\n// catch and re-run only the failed subset, or pre-validate rows\ntry {\n  await duplicateInternalTableRows(table)\n} catch (e) {\n  // inspect failed rows log, repair schema/data, retry\n}","handlingStrategy":"retry","validationCode":"// pre-validate rows against the destination table schema before bulk insert\nconst valid = rows.every(r => Object.keys(r).every(k => k in table.schema))","typeGuard":"function matchesSchema(row: Record<string, unknown>, table: Table): boolean\n  return Object.keys(row).every(k => k in table.schema)","tryCatchPattern":"try {\n  await duplicateInternalTableRows(table)\n} catch (e) {\n  if (/Failed to copy .* row\\(s\\)/.test(e.message)) {\n    // inspect failed-row logs, fix schema/data, then retry the operation\n  }\n  throw e\n}","preventionTips":["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"],"tags":["retry-exhausted","bulk-write","couchdb","data-copy"],"backgroundTag":"bulk-write-retries-exhausted","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}