Binding drift: why a source shows Needs attention, the source binding error, and how to re-attach safely
Binding drift is what happens when a source you configured no longer has a backing binding on the deployed engine. The downpipe still points at it, but the binding it reads through is gone, so the source’s next run cannot start. This page explains why drift happens, how the console shows it to you as a “Needs attention” state before any run fails, and how to re-attach the source in place. It is written for a self-hoster who has seen a source drop off the listing or a run fail with a source binding error and wants to fix it without guesswork.
The reassuring part first: drift is not a data-loss event. Your data sits untouched in Cloudflare, and the archive you already have is unchanged. What drift stops is future runs of the affected source, until you re-attach it. The rest of this page is how to recognise that state and clear it.
What drift is
Every binding-backed source is a Workers binding on the engine: a KV namespace, an R2 bucket, a D1 database, or a Secrets Store secret. The engine reads a source only through that binding. Drift is a configured source whose binding is no longer present on the deployed engine, so the run path cannot resolve it.
The console detects drift by comparing two things on every load of the Sources screen. It reads the configured sources from your downpipes (each names a binding) and it reads the bindings the deployed engine actually exposes. Any configured binding that is not in the live set has drifted. Those are surfaced first, in an explicit error state, rather than being silently dropped from the listing. Each drifted row names the missing binding, names its type, and names the downpipe or downpipes whose next run it would break, so you see the blast radius at a glance.
Needs attention is a pre-flight of the run failure
The bindings the console flags as drifted are exactly the ones the engine’s run path throws a source binding error on when it cannot find them in its environment. So the “Needs attention” tier is a pre-flight of that run-time failure: it shows you the broken source the moment the screen loads, before the next scheduled run trips over it. The same drift is also a standing item in the engine preflight check, so it appears in a support bundle as a named health signal, not a surprise.
Why it happens
There are two ways a source loses its binding, and one of them is by far the common cause.
The common cause is a redeploy that did not carry the binding. A plain wrangler deploy sets the deployed worker’s bindings to exactly what wrangler.toml lists, and removes anything not in that file. By design, wrangler.toml lists no source bindings at all, because pinning one source there would make it survive a deploy while every other console-attached source was dropped, which is worse than dropping all of them consistently. Console-attached sources live on the worker, added through the Cloudflare API by the attach path, never written into wrangler.toml. So a routine code deploy that goes straight through wrangler deploy silently wipes every console-attached source. This is the root cause behind almost every “my sources dropped off” report.
The other cause is simpler: the underlying resource was deleted. If you delete the KV namespace, R2 bucket, or D1 database that a source pointed at, its binding can no longer resolve, and the source drifts for that reason instead.
Either way, the symptom is the same. The next run of the affected source fails with a source binding error, and until the console caught drift explicitly the source would also vanish from the listing, because discovery shows only live bindings. The “Needs attention” tier exists precisely to surface that silent drop.
How to fix it: re-attach in place
Re-attaching restores the binding on the deployed engine without a terminal. From the “Needs attention” row, the Re-attach action opens the guided add-source flow for that source (or the by-id screen for a Secrets Store binding or a manually-named binding). The flow is the same no-terminal attach you use to add any source, so re-attaching is one step from where the problem is shown.
Open Re-attach from the Needs attention row
On the Sources screen, the drifted source sits in the “Needs attention” tier with a danger badge and the downpipes it breaks listed beneath the binding name. Press Re-attach on that row. Re-attach is an Owner action server-side: the engine gates the binding change to
keys.ceremony, an Owner-only capability. An Operator can open the Re-attach flow, but the Attach step itself is disabled for a non-Owner, and an Owner completes the binding change. This per-source Attach step is also opt-in dual-control gated, through the same second-owner owner-action approval mechanism that covers other high-blast-radius owner operations (armed by therequireConfigApprovaltoggle, covered on change control): if that dual control is armed, the first submission records a pending approval and returns without using the token, and a second Owner must approve before the resubmitted call is allowed to consume the token. This is a separate mechanism from the plan-hash approval that gates a restore apply. See the admin endpoints reference for the request and response shapes.Confirm the source identifiers
The guided flow re-collects the source identifiers (the namespace id, bucket name, or database id and name). Each has its own accepted format: the KV namespace id is 8 to 64 hexadecimal characters; the R2 bucket name starts with a letter or digit, then letters, digits, hyphens or underscores, up to 64 characters; the D1 database id is a UUID or 8 to 64 hexadecimal characters. These are not secret. No secret value is ever collected, even for a Secrets Store source, which is referenced by store id and secret name only.
Paste a one-shot deploy token
The attach needs a token that can edit the engine’s own Worker bindings. Paste a one-shot Cloudflare deploy token created from the “Edit Cloudflare Workers” template, scoped to the engine’s own account. It is used once for this change and never stored or logged. The engine reads its current bindings, proves the change drops none of its own, applies the change, then re-reads to verify. If it has any doubt it refuses without writing and points you at the deploy path instead.
Watch the bounded post-attach poll, then revoke the token
After the change lands, the console runs a bounded wait-for-the-deploy poll so the listing reflects the new binding once Cloudflare has applied it, rather than showing a stale state. When the source reappears as attached, revoke the deploy token on the same Cloudflare API Tokens page. The token’s real control is revoking it after the change, not its expiry.
If you would rather not paste a token, the flow offers a fallback: it generates the exact wrangler.toml stanza and the deploy command so you can apply the change with your own Cloudflare login, which needs no token. That path is the collapsed alternative, not the primary one.
Recording an identifier override
The re-attach flow above collects the source identifiers for you at the moment you fix drift. You can also record them ahead of time on the downpipe itself, in the source editor’s advanced settings, so the id a re-attach needs is already on file. Each field is optional and matters only when a downpipe is not resolving its source through the live binding. Recording the id there is what lets a deploy-dropped binding be re-attached in place.
| Override field | Source type | Format |
|---|---|---|
| Namespace ID override | KV | The KV namespace id, 8 to 64 hexadecimal characters (a real id is 32 hex). |
| Bucket name override | R2 | The exact R2 bucket name: a leading letter or digit, then letters, digits, hyphens or underscores, up to 64 characters. |
| Database ID override | D1 | The D1 database id, a UUID or 8 to 64 hexadecimal characters. |
These are the same identifiers the Finding the ids for a manual attach table tells you where to read from your Cloudflare dashboard. Each is configuration rather than a secret, and the console sends one to the engine only when you fill it in and it matches the source type.
Why re-attach is safe
The reason a token broad enough to edit bindings is not dangerous here is the attach harness. The engine never blindly overwrites its bindings the way a plain deploy does. It reads its current bindings, computes the change as a strict superset that adds the source binding and drops none of its own (its Durable Objects, the archive destination, its keys), applies it, and re-reads to confirm everything survived. The change is audited by binding name. So re-attaching one source can never quietly remove another binding the engine depends on.
What a drop and re-attach do to your run history
A drop does not orphan or fork the affected downpipe’s run history, and a clean re-attach resumes the same chain. That matters because the history is what a compliance reader reads: a break here would make a downpipe’s own record of itself a lie. It does not happen, and this is what you see instead.
A run you trigger while the source is detached fails, with the same source binding error the run path throws when it cannot resolve a binding. In the Runs view it lands as a failed run with a short coarse reason, exactly as any failed run reads. Backups have stopped for that source until you re-attach it, which is the honest state.
That failed attempt does not advance your lineage. Your last proven backup stays the last successful run from before the drop; the failed run does not become your latest backup, and it does not move the marker your next run chains onto. So the drop widens the gap since your last good backup, but it does not corrupt the record of what that last good backup was.
When you re-attach the same source, the next successful run resumes the same chain. It runs under the same downpipe, continuing your existing history rather than starting a new one, and it links back to that last successful run from before the drop, so the failed attempt sits between two good runs without breaking the line between them. No run is orphaned, and no second, forked copy of the downpipe appears.
What you should not see, and what it would mean
The regressions this behaviour guards against would be visible: a second, duplicate downpipe for the same source, a run history that reset to empty after the drop, or the failed detached run standing in as your latest good backup. If you ever see one of those after a drop and re-attach, treat it as a real fault and capture the Runs view, because none of them is the intended outcome. “The same source” here means the same binding name; re-attaching under a different binding identity is a different source and correctly starts its own history.
Honesty about what re-attach proves
Re-attaching makes the binding present on the engine. Presence is not the same as a working source. The binding being there does not by itself prove the source reads cleanly, the identifiers are right, or the next run will succeed. Confirm it two ways. Watch the post-attach poll show the source as attached, then run the downpipe and confirm the run succeeds. And remember the wider rule that runs through all of downpipes: a source is only genuinely protected once you have a proven restore of it, not merely a backup that ran. A green run is necessary but not sufficient; recoverability is what protection means.
Re-attaching reduces the chance of recurrence, it does not eliminate it
The pre-deploy reconcile described below makes a binding-dropping deploy far less likely, but it is not a guarantee that drift can never recur. A deploy that bypasses the reconcile, or a deleted resource, can still cause drift. Treat the “Needs attention” tier and the preflight check as your standing detection, and re-attach when they fire.
Prevention: the pre-deploy reconcile
The durable fix for the common cause is to stop a deploy from dropping bindings in the first place. downpipes ships a pre-deploy binding reconcile for exactly this. Before a deploy, it reads the live worker’s current bindings from the same Cloudflare script-settings endpoint the attach path uses, and regenerates the deploy configuration as the committed wrangler.toml plus every live source binding it does not already declare. The deployed configuration is then a strict superset of the live source bindings, so the deploy cannot drop one. The live worker is treated as the source of truth for what is attached, and the reconcile carries it forward verbatim.
The reconcile is fail-safe. If it cannot read the live bindings and so cannot prove the deploy preserves your sources, it refuses to produce a deploy configuration and stops the deploy, rather than letting a binding-dropping deploy proceed. Two honest exceptions are handled explicitly: a worker that does not exist yet is a first deploy with nothing to preserve, so it proceeds with wrangler.toml unchanged; and an operator who genuinely intends a reset with no sources to preserve can opt in with an explicit override. The full mechanism, including the generated wrangler.deploy.toml and the override, is documented in deploy safety and bindings.
Alongside the reconcile, the engine preflight check probes for drift ahead of a run. It enumerates every configured source binding, confirms each is present in the engine’s environment, and reports any that are missing along with the downpipes they break and a remediation line. So between the console’s “Needs attention” tier, the preflight check, and the pre-deploy reconcile, drift is detected early and prevented at its common cause, even though it can never be made strictly impossible.
Where this fits
- Deploy safety and bindings is the full account of the pre-deploy reconcile and the generated deploy configuration that prevents drift.
- Connect a source is the guided add-source flow, the same one Re-attach opens.
- Cloudflare token scopes explains the one-shot deploy token and why it is necessarily broad.
- Prove recoverability is why a re-attached, running source is not yet a protected one.
- Troubleshooting collects the symptoms, including the source binding error, with their fixes.
Last updated .