Cirra AI Article
Salesforce UNABLE_TO_LOCK_ROW: Fix Shared Parent Locks
Diagnose Salesforce UNABLE_TO_LOCK_ROW in 2026: a contention map, hottest-parent share formula, Winter '27 API 68.0 Bulk API and Data Loader serial limits, and a one-variable sandbox worksheet.

Summary
- 01Analyze candidate lock targets rather than failed input rows: child writes can lock shared parents, and lookup, roll-up and sharing rules can add targets within the same transaction.
- 02Preserve job evidence before it expires, join failed rows by stable ID, and map each row to candidate targets, possible concurrent writers, supporting logs and a next test.
- 03Compare job windows in one time zone. Missing logs and high retry counts cannot identify the competing transaction or prove that no other writer existed.
- 04Serial processing is documented for Bulk API (version 1) and Data Loader's Bulk API path. Bulk API 2.0 documents only parallel mode and creates batches automatically.
- 05Test exactly one approved change in a sandbox, repeat baseline and changed attempts, and compare failed unique rows. Smaller batches and parent sorting are options to test, not guaranteed fixes.
Inside this article
- 01Executive Summary
- 02Introduction and Background
- 03Anatomy of the Error: A Taxonomy of Lock Targets
- 04Building the Contention Map
- 05Correlating Timing and Concurrent Writers
- 06Choosing One Controlled Intervention by API Mode
- 07Data Analysis and Evidence
- 08Implementation Guidance: From Evidence to Approved Change
- 09Frequently Asked Questions (FAQs)
- 10Implications and Future Directions
- 11Conclusion
Executive Summary
UNABLE_TO_LOCK_ROW is the Salesforce API status code for a deadlock or timeout condition [1]. A transaction that cannot get a lock waits at most 10 seconds before it gives up [2]. In data loads the row that fails is often not the root of the problem: a DML (data manipulation language) operation on one record also locks related records, and inserting an Opportunity locks its parent Account [3]. Salesforce's own locking reference says the applicable rules are additive, so every row that matches the scenario has to be read [3]. The practical unit of analysis is therefore the candidate lock target (a parent, a looked-up record, a group membership table), not the input row.
This report, anchored to Winter '27 (API version 68.0) [4], proposes a contention map and an experiment worksheet. The map joins each failed row to its parent or lookup ID, a candidate lock reason, a possible concurrent writer, a supporting log and a next test. One descriptor, the hottest-parent share (rows for the busiest candidate parent divided by rows with a known parent, reported next to the unknown-parent count), summarizes input concentration. It is not a Salesforce threshold and not a failure predictor. The 10,000-child guidance Salesforce publishes concerns child records stored under one parent [5], which is a different quantity from the rows in a single load file.
Mitigation depends on the API actually in use. Bulk API (version 1) jobs accept a serial concurrency mode [6], and Data Loader exposes serial processing only on its Bulk API path [7]. The Bulk API 2.0 create-job documentation states that only parallel mode is supported [8], and Data Loader's Bulk API 2.0 option ignores both batch sizes [7]. Even a serial job can overlap with parallel jobs, leaving a small chance of locking [9]. Smaller batches and parent sorting are therefore options to test, not guaranteed fixes: published guidance disagrees on batch size [10] [11], and sorting only helps when the competing writer is the load itself [12].
The recommended workflow is to preserve the preflight evidence, secure approval for one scheduling or configuration change, run it in a sandbox, and compare before and after attempts only when everything else stayed the same. This report presents no load, benchmark or locking experiment results, so every explanation below is a hypothesis until a controlled result supports it, and it claims no release-specific change to locking behavior.
Introduction and Background
Row-lock failures are a specialist but persistent problem for Salesforce administrators, RevOps (revenue operations) data operators and implementation partners. The error text, "unable to obtain exclusive access to this record", names no culprit. A bulk load of 50,000 Opportunities can fail on a few hundred rows while the underlying contention sits on a handful of Account records that the file never lists as a target. Salesforce's Trailhead material calls record locking errors a common problem when coding data migrations [13], and the Bulk API guide notes that locks and contention become an issue mainly with large data volume objects or large jobs [14].
This explainer targets one decision: is the contention coming from shared parent records, lookup or roll-up relationships, overlapping jobs, or group-maintenance operations, and which single controlled change should be tested first? It is deliberately not a general Flow debugger and not a failed-row replay tutorial. Selective replay and result accounting belong to a separate partial-load recovery guide, which complements this diagnosis.
Release anchor and scope
Salesforce's releases page announces that Winter '27 is here [15], and the version identifies as API 68.0. The Salesforce Admin Blog listed September 4, October 2 and October 9 as the production release weekends [16] and refers readers to the maintenance calendar for instance-specific windows [16]. The Bulk API guide used here is stamped Version 68.0, Winter '27 [14], and so is the Data Loader guide. Several mechanics cited below come from older engineering blog posts, notably the 2014 record locking cheat sheet. Those sources explain mechanisms but are not a current universal limits table, so readers should record the API version, edition and test date of their own org when they run the experiments described later.
This report claims no change in record locking behavior in Winter '27, and longstanding locking behavior should not be read as new in this release. Where this report says "documented", it means documented in the cited page on the access date, 2026-10-31.
Who benefits from a contention map
- Admins running ad hoc loads gain a way to explain a failure to colleagues who own competing integrations.
- RevOps data operators gain a repeatable worksheet for scheduling windows.
- Implementation partners gain evidence to attach to a change request before altering concurrency or automation.
- AI-assisted workflows gain a structured evidence format, because a model can group sanitized errors and join stable IDs but cannot observe transactions it has no logs for.
Anatomy of the Error: A Taxonomy of Lock Targets
What the platform documents
Salesforce uses locks to preserve referential integrity. The cheat sheet organizes locking into object-specific, custom configuration and sharing categories [3] and says the information is additive. A load that touches an Opportunity with a roll-up summary field on its Account and a custom lookup can therefore hit several lock targets in one transaction. The bullets below separate those targets so each can be verified on its own.
Categories of candidate lock targets
- Parent of a child record (object-specific). The cheat sheet's worked example says an Opportunity insert locks the parent Account. Salesforce Help describes the master-detail case: a second transaction acting on a related child must wait up to 10 seconds for the parent lock [17], and a vendor troubleshooting page repeats that updating a master-detail child also locks the parent [18]. Trailhead warns of a high risk that an account update fails because a previous one still holds the lock [5].
- Lookup targets (custom configuration). Every insert or update locks the target record of each populated lookup field [5].
- Roll-up summary parents (custom configuration). The cheat sheet's example identifies the master record as locked when a roll-up summary field exists. A practitioner article describes the parent being locked during recalculation [19].
- Sharing and group membership. Role hierarchy, territory hierarchy and group member changes need an organization-wide group membership lock [3], and Salesforce Help advises waiting before trying such a change again [20].
- Ownership skew. Architect guidance recommends an owner-to-records ratio of 1:10,000 [21].
- Apex explicit locks. A
FOR UPDATEquery waits at most 10 seconds for a lock another client holds. A practitioner article notesFOR UPDATEis an Apex-only construct (Source: dev.to). - The same job competing with itself. Contention is possible inside a single process when updates run multi-threaded, and Bulk API processes batches in parallel by default, so batches within one job can collide [22].
Lock duration: why triggers and flows matter here
Locks last for the length of the transaction. Salesforce Help lists concurrent DML, Apex triggers and Bulk API imports among common triggers of the error [2], and a practitioner source states that a record stays locked from the start of the DML operation until the execution context completes [23]. This report does not debug automation logic. It treats slow synchronous automation as a duration multiplier on the candidate targets above, and Salesforce's lookup-skew article frames every mitigation as reducing the frequency and duration of the offending locks.
Not the same thing: approval and business locks
An approval process can lock a record against edits, and the API reports that case with a separate code, not a deadlock or timeout. Business locks follow approval configuration; for example, in a classic approval lock, master-detail related-list items cannot be edited [24]. Database contention is transient and resolves when the competing transaction ends. The remedy for one is not the remedy for the other, so this report does not prescribe unlocking records through approvals as a way to clear a row-lock failure.
Building the Contention Map
Capture before interpreting
Before any hypothesis, capture the evidence that will be lost first. Job status and batch results for completed Bulk API jobs are available for 7 days, after which the data is deleted [14], and Data Loader's own log is a chronological file named sdl.log [25]. Record these fields for every failed load:
- Exact error text and status code, including whether the row failed alone or as part of a failed batch.
- Affected row identifiers, object, operation (insert, update, upsert, delete) and the external ID or record ID used.
- API mode and client, for example Data Loader with its SOAP default, Data Loader with Bulk API, or an integration tool.
- Job IDs, batch IDs, start and end times in one stated time zone (UTC is the simplest choice).
- Overlapping known jobs, including integrations, scheduled Apex and manual loads.
Result files differ by API. Bulk API 2.0 notes that the order of failed records is not guaranteed to match the original job data [26], so rows should be joined back by stable ID rather than position. To find the parent of each failed row, take the child record IDs from the success or error file and run a read-only query in a sandbox first, for example SELECT Id, AccountId FROM Opportunity WHERE Id IN ('<id1>', '<id2>'), then group the results by AccountId. For failed inserts that have no record ID yet, look up the parent column in the original load file by row number or external ID instead, and count rows per parent in a spreadsheet pivot table. Data Loader writes an error file with a column describing why the load failed [25].
Inventory the relationships you can see
Object Manager is the native starting point for a relationship inventory; Trailhead shows the path from Setup through Object Manager to an object such as Account [27] and notes that roll-up summary fields are defined on the master side of a master-detail relationship [27]. For each object in the load, list its parent lookups, master-detail parents, roll-up summary fields, and any trigger, flow or workflow that updates another record. The permission needed to view this metadata depends on the org's profile and permission set design; this report does not assume a single required permission, so confirm access in a sandbox first.
(Hypothetical Example) A synthetic fixture
Table 1 below uses an invented dataset of twelve Opportunity rows. All identifiers are fictional, no customer data is involved, and no performance claim is made. Each row carries the worksheet columns: row ID, parent or lookup ID, candidate lock reason, concurrent writer, supporting log and next test. The "reason" cells restate documented mechanics; the "concurrent writer" cells are placeholders that stay unconfirmed until a log supports them.
| Row ID | Parent / lookup ID | Candidate lock reason | Concurrent writer | Supporting log | Next test |
|---|---|---|---|---|---|
| R01 | ACC-A | Child write can hold the parent Account lock [5] | Unconfirmed: same load, other batch | Bulk job batch IDs | Group by ACC-A in one batch |
| R02 | ACC-A | Same parent as R01 | Unconfirmed | Bulk job batch IDs | As above |
| R03 | ACC-A | Same parent; a roll-up summary field would add the master record | Unconfirmed: roll-up recalculation | Field inventory in Object Manager | Check whether a roll-up exists |
| R04 | ACC-A | Same parent | Unconfirmed | Bulk job batch IDs | As above |
| R05 | ACC-A | Same parent | Unconfirmed | Bulk job batch IDs | As above |
| R06 | ACC-B | Parent Account | Unconfirmed: scheduled integration | Integration run history | Compare run window in UTC |
| R07 | ACC-B | Parent Account | Unconfirmed | Integration run history | As above |
| R08 | ACC-B | Parent Account | Unconfirmed | Integration run history | As above |
| R09 | ACC-C | Parent Account | None identified | Debug log (empty) | Do not infer "no concurrency" |
| R10 | ACC-C | Parent Account plus custom lookup target REG-1 | None identified | Debug log (empty) | Count rows per lookup target |
| R11 | ACC-D | Parent Account | None identified | None | None needed |
| R12 | (blank) | Unknown parent | Unknown | None | Resolve parent before analysis |
Table 1 shows why the input row is the wrong unit. Rows R01 to R05 point at the same candidate target, so they can contend with each other whenever they land in different parallel batches, whereas R12 cannot be analyzed at all until its parent is known. The table also encodes restraint: R09 and R10 have empty debug results, and an empty result does not show that nothing else was writing, since debug logs are retained for limited periods and capped in size, as the next section details.
The hottest-parent share
Define the descriptor exactly: hottest-parent share = rows for the busiest candidate parent ÷ rows with a known parent, reported together with the unknown-parent count. In the fixture, ACC-A has 5 rows, ACC-B 3, ACC-C 2 and ACC-D 1. Eleven rows have a known parent, one has none. The hottest-parent share is 5 ÷ 11 = 45.5%, with 4 distinct parents and 1 unknown-parent row.
Treat this as an input concentration descriptor only. It is not a Salesforce skew threshold and not a predicted failure probability. Two reasons keep it honest. Salesforce's 10,000 figure is a statement about child records associated with one parent in the org: Trailhead defines data skew as more than 10,000 child records associated with the same parent [5], Architect guidance defines skew as a few parent records with many children and gives 1:10,000 as the ratio at which performance degradation starts [21], and neither compares to the rows in one load file. And an input distribution cannot reveal every transaction that touches the same parent, so it cannot prove which process held a lock.
Which fields are safe to aggregate
The aggregation can rely on identifiers and categorical fields: parent IDs, lookup IDs, object name, operation, batch ID, error code, start and end timestamps. Free-text fields, names, e-mail addresses and any customer content do not belong in an evidence map shared with an assistant or a vendor. This is a data-handling recommendation rather than a Salesforce rule, and teams should apply their own policy.
An attempt that changed batch size, sort order and job schedule at the same time cannot support any claim about which change helped.
Correlating Timing and Concurrent Writers
Build a timeline in one time zone
Convert every job window to the same zone before comparing. Candidate competing writers fall into groups with different evidence sources:
- Bulk API jobs from any client. The Bulk Data Load Jobs page is reached from Setup by entering BulkDataLoadJobs in Quick Find [14], and it tracks jobs and batches created by any client application [14].
- Batch and scheduled Apex. Batch Apex is monitored from Setup through Apex Jobs and scheduled Apex through Scheduled Jobs.
- Group maintenance, deployments and tests. Salesforce Help advises waiting and retrying group membership changes later rather than overlapping them [20].
- Another user or integration editing the same parent. A background-job check is also the first tip in a deployment tool's troubleshooting page [10].
Why an empty log proves little
Debug logs are limited to 20 MB each [28], monitoring logs are retained for seven days [28], and trace flags are disabled when an org generates more than 1,000 MB of logs in a 15-minute window [28]. If a needed log is missing, ask the operator who owns the integration or deployment for its run history and scheduler configuration rather than concluding that no other writer existed. Confirm in the target org which permission is needed to view debug logs.
Retry counters are partial evidence
For Bulk API 2.0 the job-level retries property counts repeated attempts caused by a problem such as a lock [14], and a batch can end in a TooManyLockFailure state when too many lock failures occur [14]. A high retry count is consistent with contention but does not identify the competing transaction.
Where an AI assistant fits
An authorized AI assistant can do bounded, read-oriented work: group sanitized error rows, join stable IDs to parent IDs, count rows per candidate parent, inventory the lookup and master-detail fields it can see, and draft the evidence map for human review. A hosted admin MCP (Model Context Protocol) server operates as the connected Salesforce user, so what it can describe or query is bounded by that user's permissions, and write actions belong behind explicit human approval. The assistant cannot infer a missing log, observe a transaction it has no record of, approve its own change or bypass permissions. Any explanation it produces is a hypothesis until a controlled result supports it. Native Salesforce screens remain the first choice for the facts themselves.
Choosing One Controlled Intervention by API Mode
What each path actually exposes
Table 2 below summarizes the documented controls for the paths most often involved in loads. It is a comparison of controls, not of products. The column to read first is "serial option", because teams often assume a universal serial toggle that does not exist.
| Path | Serial option | Batch controls | Documented lock behavior and caveats |
|---|---|---|---|
| SOAP API / REST sObject Collections | No job-level concurrency mode found in the pages read; concurrency comes from the caller's own threads, and multi-threaded updates can contend [3] | Create and update calls take at most 200 records (see the Data Loader row for the documented SOAP maximum) | Child writes lock the parent for the transaction [17] |
| Bulk API (version 1) | Job-level concurrency mode; serial is the documented fallback when parallel produces too many failures [6] | You create the batches yourself | Waits a few seconds on a lock before failing the record [14]; a troubled batch is requeued up to 10 times [14] |
| Bulk API 2.0 | None configurable: only parallel mode is documented [8] | Batches are created automatically [29] | Failed batches are retried automatically; automatic record lock handling is documented only as a non-generally-available pilot [30] |
| Data Loader | Serial mode available only with the Bulk API option [25] | Import maximums of 200 (SOAP) and 10000 (Bulk API) [7] | Data Loader uses SOAP by default; with the Bulk API 2.0 option neither batch size is used |
| Third-party integration tools | Tool-specific. One connector documents a concurrency property that applies to Bulk API v1 only [31]; another documents a serial load option [32] | Tool-specific | Some tools use Bulk API by default [33], so the actual API mode must be read from the tool's configuration and run log |
The matrix leads to a conclusion that matters for the experiment: serial processing is a documented control for Bulk API (version 1) and for Data Loader's Bulk API path, and not for Bulk API 2.0. Salesforce's create-job page adds that when other modes are added, the mode will be chosen automatically by the API and will not be user configurable [8]. Do not show a serial toggle for Bulk API 2.0 in a runbook, and verify the current contract in the version of the developer guide that matches your org before changing a job definition. Salesforce also recommends Bulk API 2.0 for operations above 2,000 records [34], which means many teams will have no serial option available and must fix contention by data shape and schedule.
Interventions worth testing, in order of isolation
- Isolate competing writers. Pause or reschedule the other known job and repeat the load. A deployment tool suggests pausing long-running jobs before retrying to confirm whether they are involved [10] and advises avoiding nested transactions that update parent and child records together [10]. This tests the "overlapping jobs" hypothesis without touching the load.
- Reorganize children that share a parent. For Bulk API, Salesforce documents organizing records by parent so all records referencing the same account sit in a single batch [9]. Trailhead gives the same presort advice for parallel batches [13], a deployment tool recommends sorting by parent [10], and a community answer to a 90,000-record Opportunity load proposes sequencing the inbound Opportunities by Account Id [35].
- Change batch size only where the API allows it. Data Loader exposes a setting on its SOAP and Bulk API paths; Bulk API 2.0 does not.
- Test serial processing only on a documented compatible path. That means Bulk API (version 1) or Data Loader with Bulk API enabled. A trade-press article recommends serial processing with parent-sorted data for Bulk API ETL loads [23].
- Handle group-maintenance operations as separate serial work. The Bulk API guide lists user creation, ownership updates under private sharing, role updates and territory hierarchy updates as operations likely to cause lock contention that call for serial mode [14].
Why batch size and sorting are options, not guaranteed fixes
Published advice conflicts, which is itself evidence that no universal rule exists. A deployment tool's page recommends reducing batch size to minimize contention [10], and a training site says smaller batches release locks sooner [19]. A community answer to a large Bulk API question advises leaving the batch size at 10000 records, arguing that shrinking batches can make contention worse when one parent has many children [11]. Salesforce's own Bulk API planning guidance frames batch size mainly as a throughput and timeout setting rather than a lock-contention fix: it says to start at the 10,000-record maximum, reduce the size if a batch times out, and avoid smaller batches because they increase the total number of batches and the risk of reaching the daily batch limit [9]. A 2014 community answer reports that a 200-record batch size plus Data Loader serial mode cleared errors in one trigger-driven case [36], but such reports are anecdotes about a single org, not controls. A trade-press article also describes Bulk API as splitting records into 200-record batches [23], while Salesforce documents batches of up to 10,000 records, so the number of rows in one lock-holding transaction depends on the API path in use.
Sorting has a limit too. It only helps when the competing writer is the load itself. If an integration, a scheduled Apex job or a group-maintenance operation touches the same parent, a perfectly sorted file will still collide with it. Salesforce says so in the serial case: serial-mode batches can run at the same time as parallel jobs, so a small chance of record locking remains. Salesforce also advises avoiding serial mode unless parallel mode would otherwise result in lock timeouts [14], and notes the cost is more processing time [14].
Other documented but heavier levers exist, and each needs approval because it changes behavior beyond the load. The Large Data Volumes guide suggests disabling Apex triggers, workflow rules and validations during loads [37] and using the defer sharing calculation permission.
Retry is a different tool
Retry logic addresses transient contention. A training source argues retries often succeed because lock periods are short [19]. A retry strategy does not tell you which target was contended, which is why it comes after diagnosis and belongs with the partial-load recovery process.
- Job-level concurrency mode supports serial processing when parallel processing produces too many failures.
- You create the batches yourself.
- Serial batches can still overlap with parallel jobs, leaving a chance of record locking.
- No configurable serial mode is documented.
- Batches are created automatically; Data Loader uses neither batch-size setting on this path.
- Plan around schedule and data shape because no serial toggle is documented.
Data Loader exposes serial processing only on its Bulk API path. Verify the documented controls for the API version used by the org.
Data Analysis and Evidence
Documented numbers that frame the experiment
The values below are limits and timings from Salesforce documentation, collected on 2026-10-31. They describe thresholds in the platform, not outcomes of any load.
- 10 seconds: maximum wait for a lock before the transaction times out [2].
- A few seconds: Bulk API (version 1) wait on a lock before marking a record failed.
- 10 retries: requeue limit for a troubled Bulk API batch.
- 7 days: retention of Bulk API job status and results [14].
- 20 MB, 7 days, 1,000 MB per 15 minutes: debug log size cap, monitoring-log retention and trace-flag shutoff threshold [28].
Source discrepancies to carry into the worksheet
Three discrepancies deserve explicit mention. First, retry behavior differs between Bulk API (up to 10 requeues for lock problems) and Bulk API 2.0 (automatic retries of failed batches) because the two APIs are documented separately. Second, the Bulk API 2.0 comparison material advertises automatic retry of failed records, yet the only Bulk API 2.0 lock-handling statement in the cited documentation is the non-generally-available pilot, so it does not state how a lock-failed record is treated by default in Bulk API 2.0. Third, the 10,000-children figure is a definition in training material [5] and a ratio in architecture guidance [21], not an enforced limit. Readers should treat each as a reason to measure their own data, not as a pass or fail test.
The experiment worksheet
Table 3 is the record to fill in for each attempt. The cells describe what to enter; the result cells are intentionally blank because no experiment was run for this report. Each attempt should differ from the baseline by exactly one variable.
| Field | Baseline attempt | Attempt with one change |
|---|---|---|
| Dataset scope | Same file, same row IDs (state count) | Same file, same row IDs |
| Environment | Sandbox name, edition, API version (for Winter '27: 68.0), test date | Identical |
| API mode and client | For example Data Loader, Bulk API, serial off | Identical except the variable under test |
| Batch settings | Batch size, concurrency mode (or "not configurable" for Bulk API 2.0) | Changed value, or unchanged |
| Interfering jobs | Known jobs and windows in UTC | Same list; note any that differed |
| Elapsed time | Start and end in UTC | Start and end in UTC |
| Successes | Count | Count |
| Failed unique rows | Count of distinct row IDs, not error lines | Count of distinct row IDs |
| Error categories | Counts by status code (lock timeout, other) | Counts by status code |
| Timestamp of each failure | Listed | Listed |
| Verdict | Observation only | Compare only if exactly one variable changed |
The table's last row is the discipline that matters. An attempt that changed batch size, sort order and job schedule at the same time cannot support any claim about which change helped. Run the baseline at least twice, because a single baseline cannot show how much the outcome varies when nothing is changed, and repeat the changed attempt for the same reason. Compare failed unique rows rather than error lines, since Bulk API retries and whole-batch failures can inflate raw error counts.
Implementation Guidance: From Evidence to Approved Change
A seven-step protocol
- Capture the exact error and evidence listed earlier, including job IDs and times in UTC, before anything is retried.
- Separate the error class. Confirm the status code is the deadlock or timeout condition, not an approval lock.
- Build the candidate-target map from the relationship inventory and automation list, then compute the hottest-parent share and unknown-parent count.
- Overlay the timeline of known jobs and request missing logs from their operators.
- Choose one intervention from the ordered list, consistent with the API actually used.
- Obtain approval for the scheduling or configuration change from the owner of the affected integration or automation, and run it in a sandbox first.
- Record before and after attempts in the Table 3 format and preserve the preflight evidence with them.
Decision cues, labelled as hypotheses
- If failed rows cluster on a few parents and the Bulk job batches interleave those parents, test regrouping children by parent.
- If failures align with a known integration window, test moving one of the two jobs, since sorting cannot help against an outside writer.
- If the load is Bulk API 2.0, plan around schedule and data shape because no serial toggle is documented.
- If group membership, role or territory changes are in the window, treat them as separate serial work and avoid overlapping them with loads.
- If the load already runs serially and still fails, look for parallel jobs from other clients.
An assistant can prepare steps 3 and 4 and draft the approval request, but the change, the sandbox run and the decision remain with the people who own the org. Where the work needs both a clean sandbox and a bulk data operation, an admin MCP server acting as the connected user can assist with inventory and, with explicit approval, with configuration steps, always within that user's permissions and the org's change-control process.
- 01Capture and classify
Preserve exact errors, affected IDs, API mode, job IDs and times in UTC. Confirm the status code describes a deadlock or timeout rather than an approval lock.
- 02Map candidate targets
Inventory relationships and automation, then map candidate targets and compute the hottest-parent share alongside the unknown-parent count.
- 03Correlate concurrent writers
Overlay known job windows in the same time zone and obtain missing logs from the operators who own those jobs.
- 04Choose one intervention
Select a single scheduling, data-shape or configuration change that the API actually supports.
- 05Obtain approval and test
Have the affected integration or automation owner approve the change, then run it in a sandbox first.
- 06Compare repeated attempts
Repeat baseline and changed attempts. Compare failed unique rows only when exactly one variable changed, and preserve the preflight evidence.
Compare before and after attempts only when exactly one variable changed.
If batch size, sort order and schedule changed together, the attempt cannot show which change helped.
Frequently Asked Questions (FAQs)
What does the Salesforce unable to lock row error mean?
It is the status code for a deadlock or timeout condition: a transaction waited for a record that another transaction held and gave up after about 10 seconds [2].
What is the salesforce unable to lock row error fix?
There is no single fix. Identify the contended target, find the competing writer, and then test one change. Salesforce frames mitigation as reducing the frequency and duration of locks [38].
Does reducing batch size fix an UNABLE_TO_LOCK_ROW error?
Sometimes. A deployment vendor recommends it [10], while a community answer argues the opposite when one parent has many children [11]. Test it where the API exposes the setting, and do not apply it to Bulk API 2.0, where batches are created automatically.
How do record locks behave in a parent-child data load?
Child DML locks the parent for the transaction [17], so children of the same parent in different parallel batches compete. Architect guidance describes row-lock contention emerging during concurrent operations and recommends sorting loads by parent ID [12].
What is the difference between parallel and serial mode in Bulk API?
Parallel runs batches concurrently and can cause lock contention, whereas serial mode finishes each batch before starting the next, at the cost of longer processing [14].
Does Bulk API 2.0 have a serial mode?
The documented create-job contract says only parallel mode is supported, and Salesforce adds that when other modes are added, the mode will be chosen automatically by the API and will not be user configurable [8]. Verify against the guide for your API version.
Which Data Loader setting changes this?
Enable the Bulk API option and its serial mode; serial mode is available only with Bulk API [25].
Can an Apex trigger cause UNABLE_TO_LOCK_ROW?
Apex triggers are listed among common triggers of the error [2]. A trigger that updates the same parent as the load adds a competing writer within the same transaction.
How can a shared-parent Account problem be found?
Count failed and attempted rows per parent ID, report the hottest-parent share and unknown-parent count, and check whether the busiest parent also appears in other jobs' windows. Trailhead warns that updates to an Account can fail while a previous update still holds its lock [5].
Implications and Future Directions
Salesforce's guidance steers larger loads toward Bulk API 2.0 [34], which removes the serial and batch-size knobs that older advice depends on. Operators who inherit scripts that rely on Bulk API (version 1) concurrency settings should record which API each job uses (SOAP, REST, Bulk API or Bulk API 2.0) and which API version number it calls. The pilot automatic record lock handling for Bulk API 2.0 is worth watching in future release notes, but it cannot be assumed to be available in any given org.
The contention map is also a candidate for reuse. A table of documented controls by API path, checked against the guide for each release, can be refreshed each cycle, since Salesforce stamps its guides with the release and last-updated date. For AI-assisted administration, the useful pattern is evidence preparation under human control: the assistant joins IDs and drafts the worksheet, the owner of the affected integration approves a change, and the sandbox run decides whether the hypothesis survives.
Several questions remain open and are best answered by controlled tests in the reader's org: how much a given parent's child count shifts failure rates, whether regrouping children helps when integrations also write, and whether Bulk API 2.0 lock handling differs across editions. No public benchmark answering them was found.
Conclusion
UNABLE_TO_LOCK_ROW usually reflects shared lock targets and overlapping writers rather than a defect in any single row. The reliable path is to capture evidence, map candidate lock targets, correlate timing in one time zone, and then test exactly one intervention that the current API supports. Serial processing exists for Bulk API (version 1) and Data Loader's Bulk API path, not for Bulk API 2.0, and smaller batches or parent sorting are options whose effect depends on the parent distribution, concurrent jobs and automation. Keep the preflight evidence, secure approval for the change, and record comparable before and after attempts using the worksheet. Until a controlled result supports an explanation, treat it as a hypothesis.
External Sources (38)
About
Cirra AI
About Cirra AI
Cirra AI is a software company dedicated to reinventing Salesforce administration through AI-powered tooling built on the Model Context Protocol (MCP). From its headquarters in Silicon Valley, the team has built the first commercial MCP server for Salesforce administration—a hosted service that lets any MCP-compatible AI tool (Claude, ChatGPT, Cursor, and others) connect to a Salesforce org and execute admin tasks through natural language. The product gives Salesforce administrators, revenue-operations teams, and consulting partners the ability to implement configuration changes in minutes instead of hours, while respecting org permissions and maintaining full auditability. Cirra AI's mission is to "let humans focus on design and strategy while software handles the clicks." To achieve that, the company develops two complementary product lines: Salesforce Admin MCP Server – A fully hosted MCP endpoint that connects any AI tool to Salesforce in minutes via OAuth. Administrators describe what they need in plain English—create custom objects and fields, configure page layouts, manage permission sets, build flows, provision users, generate documentation—and the MCP server translates those instructions into standard Salesforce Metadata and Tooling API calls, bounded by the user's existing permissions. No local infrastructure or custom code is required: sign up, authenticate, copy the MCP URL into your AI tool, and start working. Salesforce Skills Library – An open-source collection of domain-specific skills (available at skills.cirra.ai) that supercharge AI assistants with deep Salesforce expertise. Skills cover Apex development with 150-point scoring, Flow creation and validation with 110-point scoring, Lightning Web Component development with the PICKLES architecture methodology, metadata operations, permission auditing, data and SOQL operations, org-wide health audits, architecture diagramming, and Kugamon CPQ management. The skills are installable as a single plugin for Claude Cowork, Claude Code, and OpenAI Codex, or as individual skill files for Claude web, desktop, and ChatGPT. They enable AI assistants to perform complex, multi-step Salesforce tasks independently—run a comprehensive org audit, fix issues flagged in the report, generate field descriptions at scale—without prompt-by-prompt hand-holding. Together, these products address three chronic pain points in the Salesforce ecosystem: (1) the high cost of manual administration and repetitive setup-menu navigation, (2) the backlog created by scarce expert capacity, and (3) the risk of inconsistent, undocumented changes. Early adopter feedback shows time-on-task reductions of 70–90 percent for routine configuration work.
Leadership
Cirra AI was founded in 2024 by Jelle van Geuns, a Dutch-born engineer, serial entrepreneur, and veteran of the Salesforce ecosystem with over 14 years of platform experience. Before Cirra, Jelle bootstrapped Decisions on Demand, an AppExchange ISV whose rules-based lead-routing engine is used by multiple Fortune 500 companies. Under his leadership the firm reached seven-figure ARR without external funding, demonstrating a combination of deep technical innovation and pragmatic go-to-market execution. Jelle began his career at ILOG (later IBM), where he managed global solution-delivery teams and developed expertise in enterprise optimisation and AI-driven decisioning. He holds an M.Sc. in Computer Science from Delft University of Technology and speaks frequently on AI-assisted administration, MCP integration patterns, and human-in-the-loop automation at Salesforce community events and podcasts. The leadership team includes Jeff Bajayo (VP Sales), a seasoned Salesforce and SaaS professional with over a decade of experience, and Latrice Barnett (Advisor, Marketing), who brings 10+ years of partnership and ecosystem marketing expertise from the Salesforce ecosystem.
Why Cirra AI Matters
MCP-native architecture – Rather than building a proprietary agent UI, Cirra embraces the Model Context Protocol as a universal connector, letting customers use the AI tool they already prefer—Claude, ChatGPT, Cursor, or any future MCP-compatible client—while Cirra handles the Salesforce integration layer. Deep vertical focus – The Skills Library encodes thousands of Salesforce best-practice patterns, scoring rubrics, and validation scripts that generic AI assistants lack. This domain intelligence produces higher-quality, more reliable outputs for Apex, Flows, LWC, permissions, and metadata operations than general-purpose prompting alone. Enterprise-grade security – The platform uses OAuth authentication, encrypted endpoints, and inherits the connected user's Salesforce permission model. Cirra never stores Salesforce credentials, and all actions are logged for auditability—critical requirements for regulated industries adopting AI tooling. Works for admins and partners alike – Individual administrators use Cirra to eliminate setup-menu drudgery and respond faster to business requests. Consulting firms use it to scale senior-level expertise across delivery teams, enabling more projects delivered at higher quality and lower cost through improved documentation and test coverage. Accessible to non-developers – Anyone with a paid Claude or ChatGPT subscription can install the skills and connect the MCP server. No coding, no complex integrations—just sign up and start working.
Future Outlook
Cirra AI continues to expand its capabilities with the upcoming Admin Agent (launching June 2026), which will bring fully autonomous multi-step task execution to Salesforce administration. The company is also extending platform compatibility to additional AI marketplaces and broadening its skills library to cover more Salesforce clouds and use cases. By combining open standards, domain-specific intelligence, and a relentless focus on the admin experience, Cirra AI is building the de-facto AI integration layer for Salesforce administration.
Disclaimer
This document is provided for informational purposes only. No representations or warranties are made regarding the accuracy, completeness, or reliability of its contents. Any use of this information is at your own risk. Cirra AI shall not be liable for any damages arising from the use of this document. This content was generated with assistance from artificial intelligence tools, which may contain errors or inaccuracies. Readers should verify critical information independently. All product names, trademarks, and registered trademarks mentioned are property of their respective owners and are used for identification purposes only. Use of these names does not imply endorsement. This document does not constitute professional or legal advice. For specific guidance related to your needs, please consult qualified professionals.