Which page
https://developers.cloudflare.com/workers/configuration/versions-and-deployments/gradual-deployments/#gradual-deployments-for-durable-objects
That anchor is where the API error itself sends you.
What happens
wrangler versions upload on a Worker whose config carries a [[migrations]] entry is rejected by the API:
✘ [ERROR] A request to the Cloudflare API
(/accounts/<id>/workers/scripts/<name>/versions) failed.
Version upload failed. You attempted to upload a version of a Worker that
includes a Durable Object migration, but migrations must be fully applied via
a non-versioned deployment. Refer to the documentation for more information.
[code: 10211]
To learn more about this error, visit:
https://developers.cloudflare.com/workers/configuration/versions-and-deployments/gradual-deployments/#gradual-deployments-for-durable-objects
The rule is clear and sensible. The problem is that the page it points at doesn't state it.
What that page says
The Durable Objects section explains that gradual deployments work differently because only one version of each Durable Object can run at a time, then refers the reader onward. Nothing there says a version upload carrying a migration is refused, or that the migration has to go through a non-versioned deploy.
Searching the docs repo for the error's own vocabulary returns nothing:
| search |
hits |
10211 |
0 |
non-versioned deployment |
0 |
must be fully applied |
0 |
Reproduction
Measured on wrangler 4.125.0, 2026-08-25, against a throwaway Worker that was deleted afterwards.
- Deploy a Worker with no Durable Object, so it exists:
- Add a class and a migration, then upload a version:
wrangler versions upload → exit 1, error 10211
Two adjacent behaviours worth documenting alongside it, both of which cost time to discover:
wrangler versions upload on a Worker that does not exist yet fails with "You cannot upload a new version of a Worker that does not yet exist. Please run the deploy command first." So the two-step sequence above is the only way to reach the migration error at all.
wrangler deploy never hits this, because it routes around the versions endpoint when a migration is present. Users only meet error 10211 when they upload a version explicitly.
Why it matters
Anyone running releases as versions upload plus a gradual ramp has to break that model exactly once per Durable Object lifecycle change, and go straight to 100% with a direct deploy. That's a real operational constraint on a release process, and right now you find out by hitting the error.
The same applies to [[migrations]] deletions and renames, since those produce a migration delta too.
Suggested addition
On the linked anchor, state the rule plainly: a version upload containing a Durable Object migration is rejected, and the migration must be applied by a non-versioned deploy. Naming error 10211 would make it searchable, since that string currently appears nowhere in the docs.
A sentence on what this means for a gradual-deployment workflow would help too: adding, renaming, transferring, or deleting a Durable Object class needs one direct deploy, and ramping can resume afterwards.
Which page
https://developers.cloudflare.com/workers/configuration/versions-and-deployments/gradual-deployments/#gradual-deployments-for-durable-objects
That anchor is where the API error itself sends you.
What happens
wrangler versions uploadon a Worker whose config carries a[[migrations]]entry is rejected by the API:The rule is clear and sensible. The problem is that the page it points at doesn't state it.
What that page says
The Durable Objects section explains that gradual deployments work differently because only one version of each Durable Object can run at a time, then refers the reader onward. Nothing there says a version upload carrying a migration is refused, or that the migration has to go through a non-versioned deploy.
Searching the docs repo for the error's own vocabulary returns nothing:
10211non-versioned deploymentmust be fully appliedReproduction
Measured on wrangler 4.125.0, 2026-08-25, against a throwaway Worker that was deleted afterwards.
{ "name": "probe", "main": "src/plain.js", "compatibility_date": "2026-08-01", "workers_dev": false }{ "name": "probe", "main": "src/index.js", "compatibility_date": "2026-08-01", "workers_dev": false, "durable_objects": { "bindings": [{ "name": "PROBE", "class_name": "ProbeCounter" }] }, "migrations": [{ "tag": "v1", "new_sqlite_classes": ["ProbeCounter"] }] }Two adjacent behaviours worth documenting alongside it, both of which cost time to discover:
wrangler versions uploadon a Worker that does not exist yet fails with "You cannot upload a new version of a Worker that does not yet exist. Please run thedeploycommand first." So the two-step sequence above is the only way to reach the migration error at all.wrangler deploynever hits this, because it routes around the versions endpoint when a migration is present. Users only meet error 10211 when they upload a version explicitly.Why it matters
Anyone running releases as
versions uploadplus a gradual ramp has to break that model exactly once per Durable Object lifecycle change, and go straight to 100% with a direct deploy. That's a real operational constraint on a release process, and right now you find out by hitting the error.The same applies to
[[migrations]]deletions and renames, since those produce a migration delta too.Suggested addition
On the linked anchor, state the rule plainly: a version upload containing a Durable Object migration is rejected, and the migration must be applied by a non-versioned deploy. Naming error 10211 would make it searchable, since that string currently appears nowhere in the docs.
A sentence on what this means for a gradual-deployment workflow would help too: adding, renaming, transferring, or deleting a Durable Object class needs one direct deploy, and ramping can resume afterwards.