You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
cf deploy aborts in CI on a Worker last uploaded via the script API, with no flag to override #69
We moved three existing Workers from another deploy tool, which uploads through the Workers script API, to cf. The first cf deploy --prebuilt in GitHub Actions for each Worker aborts:
▲ You are about to upload a Worker that was last updated via the script API.
│ Edits that have been made via the script API will be overridden by your local code and config.
■ Aborting the upload operation because of conflicts. To override and upload anyway, remove the `--strict` flag
We never passed --strict, and cf deploy has no such flag to remove. The deploy input for deploy (and versions upload) hard-codes strict: true, so in a non-interactive environment the last_deployed_from === "api" confirmation always resolves to abort. The same applies to the last_deployed_from === "dash" config-diff prompt.
--dry-run skips these pre-upload checks, so a dry run passes and the abort only shows up on the real deploy.
Repro
Upload a Worker via the script API (PUT /accounts/:id/workers/scripts/:name), e.g. with any non-Wrangler tool.
From a cf project with the same Worker name: CI=1 cf deploy </dev/null.
It exits 1 with the message above.
A Worker first uploaded by cf redeploys fine non-interactively, so this only blocks the first cf deploy of a Worker that another tool manages today. That is exactly the migration path, and it has to happen in CI when deploys are CI-only.
Ask
A way to confirm the override non-interactively, e.g. cf deploy --force / --no-strict (or an env var). Also, the message should not tell users to remove a flag that cf doesn't expose.
Standalone reproduction on cf 1.0.0-beta.5, Node 24.4.1, Bun 1.4.2, macOS. This uses a local mock API, dummy credentials, and a tiny prebuilt Worker. No Cloudflare account, existing Worker, or application repository is required. Telemetry is disabled.
Install in a fresh directory:
mkdir cf-69-repro
cd cf-69-repro
printf'{"private":true}\n'> package.json
bun add --exact cf@1.0.0-beta.5
Save the following as ci-repro.mjs and run node ci-repro.mjs. The script asserts the observed beta.5 behavior and removes its temporary Worker output afterward.
├ Deploy
▲ You are about to upload a Worker that was last updated via the script API.
│ Edits that have been made via the script API will be overridden by your local code and config.
■ Aborting the upload operation because of conflicts. To override and upload anyway, remove the `--strict` flag
│
◆ Deploy complete
{"exit":1,"requests":["GET /client/v4/accounts/fixture-only/workers/services/fixture"]}
The mock returns last_deployed_from: "api" on the service lookup. The CLI exits 1 before any upload. No --strict flag was supplied, and the output nevertheless tells the caller to remove it. It also prints Deploy complete after the abort.
Expected: expose an explicit way to authorize the migration in CI, and make the abort guidance refer to options actually supported by cf deploy. This reproduction exercises the script-API origin case; it does not test the dashboard-origin case.
Adding the dashboard-origin case from a production Worker deployed by Workers Builds, and a workaround (for @treeder's question). Still present in cf 1.0.0-beta.20.
What happened
Updated one secret on the Worker in the Cloudflare dashboard. The script's last_deployed_from became dash.
Every Workers Builds deploy after that (deploy command runs cf deploy --prebuilt) failed with:
Aborting the upload operation because of conflicts. To override and upload anyway, remove the `--strict` flag
Production stayed on the old version, which no longer matched the secret we had just changed. That's how a routine secret rotation became an outage.
cf deployments create (promoting an existing version)
Workaround that worked
Run one cf deploy --prebuilt interactively (in a real TTY) from a clean checkout of the same commit and answer yes at the conflict prompt. That upload resets last_deployed_from, and Workers Builds deploys succeed again afterwards. Workers Builds itself can't do this, because it has no TTY.
Where it comes from (beta.20 dist)
deploy-input-*.mjs: the deploy and versions upload inputs set strict: !0 unconditionally.
containers-*.mjs (getDeployConfirmFunction): when non-interactive and strictMode, it logs the abort and sets process.exitCode = 1.
cf deploy --help lists no --strict, --force, or --yes option, so the message's advice can't be followed.
Suggestions
Add an explicit override for non-interactive runs (e.g. --force / --no-strict, or an env var Workers Builds can set).
If only secrets changed in the dashboard, consider not treating it as a conflict. Secrets aren't in the local config, so a deploy can't overwrite them.
Make the abort message name an option that exists. (As noted above, it also prints Deploy complete after aborting.)
Activity
matthewbjones commentedon Sep 29, 2026
Standalone reproduction on cf 1.0.0-beta.5, Node 24.4.1, Bun 1.4.2, macOS. This uses a local mock API, dummy credentials, and a tiny prebuilt Worker. No Cloudflare account, existing Worker, or application repository is required. Telemetry is disabled.
Install in a fresh directory:
Save the following as
ci-repro.mjsand runnode ci-repro.mjs. The script asserts the observed beta.5 behavior and removes its temporary Worker output afterward.Complete reproduction script
Observed output:
The mock returns
last_deployed_from: "api"on the service lookup. The CLI exits 1 before any upload. No--strictflag was supplied, and the output nevertheless tells the caller to remove it. It also printsDeploy completeafter the abort.Expected: expose an explicit way to authorize the migration in CI, and make the abort guidance refer to options actually supported by
cf deploy. This reproduction exercises the script-API origin case; it does not test the dashboard-origin case.treeder commentedon Oct 12, 2026
What's the workaround when this happens?
jswny commentedon Oct 21, 2026
I am hitting this as well, have to switch off
cfin the meantime as it breaks my deploys every time I add a secret in the cloudflare dashboard :(ferdousbhai commentedon Oct 25, 2026
Adding the dashboard-origin case from a production Worker deployed by Workers Builds, and a workaround (for @treeder's question). Still present in cf 1.0.0-beta.20.
What happened
last_deployed_frombecamedash.cf deploy --prebuilt) failed with:What does not clear the
dashmarkercf workers secrets update <NAME> --worker <worker>cf deployments create(promoting an existing version)Workaround that worked
Run one
cf deploy --prebuiltinteractively (in a real TTY) from a clean checkout of the same commit and answer yes at the conflict prompt. That upload resetslast_deployed_from, and Workers Builds deploys succeed again afterwards. Workers Builds itself can't do this, because it has no TTY.Where it comes from (beta.20
dist)deploy-input-*.mjs: thedeployandversions uploadinputs setstrict: !0unconditionally.containers-*.mjs(getDeployConfirmFunction): when non-interactive andstrictMode, it logs the abort and setsprocess.exitCode = 1.cf deploy --helplists no--strict,--force, or--yesoption, so the message's advice can't be followed.Suggestions
--force/--no-strict, or an env var Workers Builds can set).Deploy completeafter aborting.)