Recover from refusals¶
When the Hub refuses an action, find the message here. This page is a lookup table: what each refusal means, whether anything was spent or created (almost always no), and what to do next.
Two kinds of "no" come back from the dashboard:
- Pre-flight refusals. Before creating a renewal, the Hub grades the request — is a live Scout bound, can the delivery land, can the key be reused, will the CA even accept the order — and refuses anything whose failure is knowable in advance. These all fire before any ACME order exists: nothing is issued, nothing is billed, no rate-limit budget is consumed. The refusal repeats identically until its cause is fixed.
- Stale offers. Every button on Manage is an offer computed from the
state at read time. If the state moved before your click landed —
another operator adopted the row, a renewal finished, a Scout went dark
— the Hub answers
409with one of the messages in the last section. That is not a fault: re-read the page; the state moved.
Where the message appears. A refused renewal shows
pre-flight refusal: <code> on the button you clicked. The full sentence
and its remedy land on the Activity page as
"Renewal refused for <hostname> — …", and in the audit log. Stale-offer
409s are deliberately not shown as errors in the dashboard — the page
just refreshes and the offer changes; you only see their message text when
driving the API directly.
Severity grades. Each pre-flight finding carries one of three grades:
- Fatal — refuses the renewal outright, never overridable.
- Cannot take effect — the renewal could be created, but delivery provably can't reach the service; refused unless explicitly overridden (the remedy text says when "proceed anyway" is a sane choice).
- Informational — a notice; the renewal proceeds either way.
Angle-bracketed parts of the quoted messages (<hostname>, <path>, …)
vary per endpoint.
Scout availability¶
The Hub will not start a renewal it cannot deliver. A Scout counts as live
when it is active and has been seen within the last 10 minutes.
| Message (as shown) | Meaning | What to do |
|---|---|---|
scout_dark — "No live scout is bound to <hostname> (last seen <when>)" |
Fatal. No Scout serves this endpoint, or the bound Scout hasn't checked in recently enough to trust with a delivery. | "Re-enroll or restart the scout" — on the host: systemctl status cyphers-scout, then restart or re-enroll it. Retry once its Last seen advances on Scouts. |
preflight_no_ack — "The scout did not answer the pre-flight check in time, so its held-key facts are unknown" |
The Scout didn't ack the pre-flight probe within its ~10 s budget — slow or lossy, not necessarily old. Fatal only when the renewal requests key reuse (an unproven Scout must not be trusted with a reuse dispatch); a notice otherwise. | "Check the scout is connected and processing commands, then retry. If the renewal must proceed without this check, set the profile to generate_new" — but prefer retrying: generate_new rotates the key and breaks any published pin. |
preflight_unsupported — "The scout did not complete the pre-flight check (older scout binary, or a transient issue)" |
Informational — the renewal proceeds without the Scout-side checks. | "Upgrade the scout to the latest release to enable pre-flight checks; renewal proceeds without it". |
Nothing was created by any of these.
Key reuse¶
These fire only on a profile with Reuse private key across renewals enabled, and they are the feature working: when reuse cannot be honored, the renewal is refused rather than silently rotating the key your pins depend on. All are Fatal, all are free, and none created an order. See Key reuse and pinning.
| Message (as shown) | Meaning | What to do |
|---|---|---|
key_reuse_adoptable — "Key reuse is requested, but the key this endpoint serves (<algo>) is at <path>, which this Hub does not manage — reuse can only load a key the scout itself holds" |
The served key exists on disk but isn't under Scout management yet. The expected first refusal when taking over an existing layout. | "Run Adopt key to bring that key under management (a one-time copy), then renew — the published pin survives. Or set the profile to generate_new, which rotates the key and BREAKS any published pin." See Adopt a private key. |
key_reuse_key_missing — "Key reuse is requested, but the scout holds no private key for this endpoint to reuse" |
The Scout holds nothing and can see nothing adoptable — usually the serving directory isn't in its cert-dirs.conf. |
"Flip the profile to generate_new for one renewal — re-publish pins afterwards — or restore the private key on the scout". First check the cert directory is listed (see Track a new endpoint, Step 4), wait a cycle, retry. |
key_reuse_algo_mismatch — "Key reuse is requested, but the scout's held key is <held> while this renewal would generate <expected>" |
The profile's Key Type doesn't match the key actually held (e.g. an rsa_4096 profile over a 2048-bit key). |
"Revert the profile's key algorithm, or rotate explicitly via generate_new". |
key_reuse_diverged — "The managed private key is no longer the key this endpoint serves — something else has rotated it (another renewer, e.g. certbot, still managing this host)" |
The adopted key and the served key have parted ways since adoption. Reusing the adopted key now would rotate what the endpoint presents — the exact outcome reuse exists to prevent. | "Stop the other renewer for this host, then re-adopt the key it left in place. Until then reuse is refused rather than rotating the served key." |
key_reuse_unsupported — "Key reuse is requested, but this scout cannot report or honor held-key facts (older scout binary)" |
The Scout answered, but in a shape that proves it predates the key-reuse protocol. | "Upgrade the scout — this scout cannot honor key reuse — or set the profile to generate_new". |
Replicated certificates¶
These fire only on a certificate that has replicas — the same certificate installed on more than one Scout. All five are Fatal and none are overridable: none can be made safe by clicking through them, because the thing they're protecting against is a Scout left serving a certificate it can no longer prove or receive.
Two different moments raise the same http01/replica fact:
replicated_requires_dns01 fires the instant you try to Adopt or repoint a
replicated certificate onto an HTTP-01 profile, before anything is ordered;
replica_needs_hub_driven_lane fires later, at renewal pre-flight, for a
certificate that reached this state some other way (a replica shows up after
the profile was already assigned). Both name the same Scouts and quote the
same remedy — replicated certificates are DNS-01-only by policy (operator
ruling 2026-08-31), not a gap Cyphers plans to close.
| Message (as shown) | Meaning | What to do |
|---|---|---|
replicated_requires_dns01 — "This certificate is installed on <N> other Scout(s) (<names>); the http01 lane never hands the issued certificate back to the Hub, so it has nothing to copy to them. Use a DNS-01 profile for this certificate, or remove the copies." |
You picked an HTTP-01 profile on Adopt or Policy for a certificate that already has a replica. |
Pick a DNS-01 profile instead, or remove the other Scout's copy first if you don't actually need it kept current. See One certificate on two servers. |
replica_key_rotation — "This certificate is installed on <N> other Scout(s) (<names>); rotating the key on this renewal would strand them serving a certificate whose key no longer matches" |
This renewal's key policy would generate a fresh key while at least one replica exists holding the current one. | "Set 'keep private key' on the profile, or remove the copies" — enable Reuse private key across renewals on the profile (Settings → Certificate issuance → Renewal Profiles), or stop treating the named Scout(s) as replicas by removing their copy. See One certificate on two servers. |
replica_key_mismatch — "<scout> (<path>) already holds a private key that no longer matches this certificate - its last copy attempt failed on a key mismatch" |
A replica's last delivery attempt already failed pairing the certificate against its on-disk key — usually its key was replaced outside of Cyphers since the last successful copy. | "Re-copy the key to that Scout, or remove its copy" — repeat the one-time hand copy (the automatic convergence sweep then re-sends the certificate within minutes), or remove the certificate from that Scout if it no longer needs it. |
replica_needs_hub_driven_lane — "This certificate is installed on <N> other Scout(s) (<names>); the http01 lane never hands the issued certificate back to the Hub, so it has nothing to copy to them" |
The renewal profile uses HTTP-01, which completes the ACME challenge and installs the certificate entirely on the Scout — the Hub never receives a copy to forward. |
"Use a DNS-01 profile for this certificate, or remove the copies" — switch to a DNS-01 profile if you need the replicas kept current automatically. |
replica_check_failed — "Could not determine whether this certificate has replicas on other Scouts (replica check failed)" |
The Hub's own replica lookup errored, so it cannot tell whether a rotation would strand anyone. It fails closed. | "Retry once the Hub database is reachable" — this is an infrastructure fault, not a configuration one. |
Replica deliveries themselves are automatic (the convergence sweep — see replicated certificates); the per-replica Deliver again button was removed. The delivery outcomes below can still appear in the Activity feed, and mean:
| Message (as shown) | Meaning | What to do |
|---|---|---|
replica_current — "<scout> already serves this certificate" |
The replica caught up between the drawer loading and the click. | Re-open the drawer; nothing to do. |
replica_delivering — "a delivery to <scout> is already in progress" |
A delivery to this replica hasn't been acknowledged yet. | Wait for it to resolve (about an hour at most), then re-check. |
no_presented_name — "<scout> serves no name this certificate carries, only a host covered by its wildcard, so Cyphers cannot tell it which directory to use. Copy the private key into that Scout's own certificate directory by hand." |
The replica only serves a host a wildcard in the certificate covers, so there is no directory both the key adoption and the delivery could agree on. | Nothing here can fix it — copy the new fullchain.pem to that box by hand after each renewal. See When a replica has to be updated by hand. |
delivery_unavailable — "Cyphers could not deliver to <scout>: <reason>" |
The Hub does not hold something the delivery needs — no owner deployment on record, or no stored copy of the issued certificate. When the owner's renewal is on the HTTP-01 lane, <reason> says so directly: that lane never hands the Hub a copy to store in the first place. |
Renew the certificate on its owner; the next issuance stores what the delivery needs. If <reason> names HTTP-01, switch the owner's profile to DNS-01 first — renewing again on HTTP-01 stores nothing new to deliver. |
no_certificate — "this endpoint has no certificate to deliver again" |
The row carries no certificate identity the Hub can ship. | Let a scan or renewal establish one first. |
These two are staleness — no refused flag, absorbed quietly, and the
page re-reads itself. You will normally see the offer simply disappear:
| Message (as shown) | Meaning | What to do |
|---|---|---|
no_live_scout — "<scout> is not currently connected - re-check" |
The replica's Scout went inactive between the drawer's read and the click. | Nothing — bring the Scout back and the offer returns. |
not_a_replica — "<scout> is not a replica of this certificate - re-check" |
The Hub no longer sees that Scout holding a lagging copy: its file was removed, or the sweep retired the observation. | Nothing, if you removed the copy on purpose. Otherwise check that the file is still there and still visible to cert-dirs.conf. |
Delivery — can the renewal take effect?¶
These grade whether an issued certificate could actually reach the service. The first two are about this endpoint's layout; the third is about the Scout's whole box.
| Message (as shown) | Meaning | What to do |
|---|---|---|
cannot_take_effect — "The scout found no served certificate file in any configured cert-dir, and no deploy hook is set — delivery cannot reach the service" |
Cannot take effect (refused unless overridden). The Scout has no path by which an installed certificate would ever be picked up by the web server. | "Add the directory containing the served certificate (e.g. /etc/ssl) to the scout's cert-dirs and reload it, or create a deploy hook". |
no_deploy_hook — "No deploy hook is configured — the service will not automatically reload after install" |
Informational — the renewal proceeds; the certificate lands on disk but the service keeps serving the old one from memory until its next reload. | "Optionally create <data-dir>/hooks/deploy to reload the service after install" — see Scout → Commands. |
sibling_renewal_active — "A renewal for <sibling> is <status> on this Scout's box — starting another renewal now can kill its hooks or verification probe" |
Cannot take effect. One renewal at a time per box: a starting renewal's pre-hook (e.g. stopping the web server) would sabotage the in-flight one's verification. | "Wait for the in-flight renewal on this Scout to conclude (the sweep retries automatically), or proceed anyway accepting the risk to its verification." |
sibling_renewal_active — "Could not prove no sibling renewal is in flight on this Scout's box (sibling check failed)" |
Same code, the fail-closed variant: the Hub couldn't check (database blip), so it refuses rather than silently skipping the guard. | "Retry once the Hub database is reachable, or proceed anyway accepting the risk to any in-flight sibling renewal." |
Provider and account¶
| Message (as shown) | Meaning | What to do |
|---|---|---|
acme_unresolvable — "ACME client not configured (no renewal profile and no ACME_EMAIL)" |
Fatal. No issuance configuration resolves for this endpoint at all. | "Attach a renewal profile to this endpoint or set ACME_EMAIL" — in practice: create a renewal profile and assign it. |
provider_eab_missing — "<Provider> requires External Account Binding (EAB) credentials, but none are configured for this provider" |
Fatal. Every order to an EAB-required provider fails at account creation, so the whole request is refused before any order is attempted. | "Configure an EAB key ID and HMAC secret for <Provider> in Settings → Certificate Providers, then retry" — see Hub — certificate providers. |
duplicate_cert_limit_risk — "This fan-out would issue <N> more identical-name certificate(s); with <M> already issued in the last <W> days that is <T>, past <Provider>'s limit of <L> identical certificates per <W> days" |
Fatal. Proceeding would exceed the provider's own published duplicate-certificate rate limit (Let's Encrypt: 5 identical-name certificates per 7 days). Refusing here protects the budget you have left. | "Share one certificate across these servings instead of one order per serving, or wait for the <W>-day window to roll before renewing again". |
duplicate_cert_limit_risk — "This fan-out brings this hostname to <T> identical-name certificates in the last <W> days; <Provider> allows at most <L> per <W> days" |
The Informational grade of the same check: still under the limit, but the headroom is nearly gone. | "No action needed now, but a further renewal within the same window may be refused". |
DNS¶
| Message (as shown) | Meaning | What to do |
|---|---|---|
manual_dns01 — "No DNS provider resolves for this endpoint, so the TXT record cannot be published automatically" |
Informational, and it fires for every DNS-01 validation method. On DNS-01 (Manual TXT) it means what it says: the renewal proceeds on the manual lane. |
Publish the record yourself — the drawer shows the exact record(s) and a Verify & Complete button when the order parks — or select a configured DNS provider on this endpoint's renewal profile. Either this Hub has no DNS provider at all, or the profile names one that has since been removed (Route 53 · Cloudflare · Google Cloud DNS). |
On an automatic profile, manual_dns01 understates what happens
The finding is raised for any DNS-01 variant with no provider configured,
but its wording assumes the manual lane. A profile set to
DNS-01 (Automatic via API) (under either spelling) does not
fall back — it dispatches and then fails at the Hub with "acme_dns01_direct
selected but no DNS provider is configured on this Hub". Treat this
finding as blocking on those profiles.
Automatic DNS-01 failures¶
These arrive as the renewal's error message (and on Activity), not as pre-flight codes. All of them happen after the order is opened but — except where noted — before the CA has been asked to validate anything, so no order was burned and nothing was billed.
| Message (as shown) | Meaning | What to do |
|---|---|---|
"<verb> selected but no DNS provider is configured on this Hub. Either configure a DNS provider … or change the renewal profile's issuance_path to local_dns" |
The profile is on an automatic DNS-01 lane and no provider resolves for it — either the Hub holds no DNS credentials, or the profile names a provider that has been removed. Deliberately fatal: an operator who asked for automation should not have it silently withdrawn. | Configure a provider under Settings → Certificate issuance → DNS provider, or move the profile to DNS-01 (Manual TXT). (The message names Settings → Advanced; that panel was renamed and now lives under Certificate issuance.) |
"DNS TXT record <name> not found. Expected value: … Still not there after 35s, asked the zone's own authoritative nameservers." |
The Hub published the record but it never became visible at the zone's own servers within the 35-second budget. | Retry — it is free. Then check the zone the registrar actually delegates to, that the credential can write (the health check only proves it can read), and that the Hub can reach nameservers on port 53. |
"DNS TXT record <name> has wrong value. Expected: … Found: [ … ]" |
Some other value is live at the challenge name. | Usually a leftover record or a concurrent order for the same name. The Hub's cleanup is value-matched on Route 53 and Cloudflare, so it never removes another order's record — and never sweeps one an older Hub orphaned. Remove stale _acme-challenge entries by hand. |
"ACME order is Invalid and cannot be finalized — <domain>: <the CA's own problem>" |
The CA looked and refused. The text after the dash is the CA's actual complaint, read out of the authorization. | Act on what the CA said. This replaced the opaque orderNotReady, which was only ever the symptom of finalizing an already-dead order. |
⚠️ orderNotReady on its own is a version tell. Builds before 2026-08-22
finalized orders the CA had already rejected and reported that generic code,
burying the reason. If you are still seeing it, the Hub needs upgrading.
CAA¶
The Hub re-checks your domain's CAA records against the provider's issuer domain before every order, fail-closed. A CAA refusal appears as the renewal's error message (and on Activity), not as a pre-flight code — but like the pre-flight, it fires before the order exists: nothing was issued or billed.
| Message (as shown) | Meaning | What to do |
|---|---|---|
"CAA preflight rejected '<domain>': CAA records at '<zone>' do not authorize '<ca-domain>'" |
The domain (or a parent zone) publishes CAA records, and none of them names this CA's issuer domain. | Add a CAA issue record authorizing the CA — or, if the records are right, fix the provider row's CAA issuer domain in Settings → Certificate Providers. Check with dig CAA shop.example.com +short (and the parent zones). |
"CAA preflight rejected '<domain>': critical CAA tag '<tag>' at '<zone>' is not supported" |
A CAA record with the critical flag set uses a tag the Hub doesn't understand, so it must refuse (that is what the critical flag means). | Review the record with your DNS operator; remove or replace the unrecognized critical-tagged record. |
"CAA preflight failed for '<domain>': DNS CAA lookup for '<zone>' failed: <error>" |
The CAA lookup itself failed — the Hub could not prove issuance is allowed, so it refuses rather than guessing. The Hub resolves through the host's own system resolvers. | Fix DNS resolution from the Hub host (split-horizon and egress rules apply as they do for any process on that host), then retry. |
Delete — a Scout still holds the certificate¶
A decision, not staleness: it repeats on every retry until the cause is gone, so the dashboard shows it and withholds the Delete offer on the same rule.
| Message (as shown) | Meaning | What to do |
|---|---|---|
"<scout> still holds <path> for <hostname>, delivered <date> — remove it from the Scout first; its next sweep releases the endpoint" (held_by_scout) |
A certificate Cyphers delivered for this name (a deployment or renewal of the Hub's names it — a certbot leftover does not count) was reported on disk by a live Scout in its latest sweep. Deleting the row now would only have that Scout's next filesystem sweep recreate it: the estate reflects what Scouts hold. | Remove the file (or its directory) on the Scout. Its next sweep — on the Scout's scan interval (set on the Hub), or immediately on a Scout restart — no longer reports it, and the offer returns. Stopping management alone does not release it. |
409s that are NOT errors — the offer went stale¶
Every message below means the same thing: the page you clicked from no longer described reality — re-read it; the state moved. Nothing failed, nothing was spent, and the dashboard deliberately shows no error for these: it silently refreshes, and the offer you clicked is replaced by whatever is now true. You'll only meet these message strings when driving the API directly.
| Message (as shown) | Meaning | What to do |
|---|---|---|
"endpoint is not unmanaged (state: <state>)" |
You clicked Adopt on a row that is no longer unmanaged — someone (or a verified renewal's automatic sibling adoption) got there first. | Re-read. The endpoint is already managed. |
| "endpoint is already unmanaged" | Demote on a row already demoted. | Re-read; done already. |
| "endpoint is not currently managed" | A policy assignment on a row that was demoted under you. | Re-read; adopt first if you still mean to manage it. |
| "a renewal is already in progress for this service" (or "…for this endpoint") | Renew Now (or + Add endpoint) raced an in-flight renewal — the in-flight dedup refused a duplicate. | Wait for it to reach a terminal state; watch the drawer's Renewals list. |
| "this service has never been observed actually serving a certificate" | Renew on an unproven endpoint: the Hub refuses to start ACME issuance against a hostname it has never seen serve. | Get it observed first — Track a new endpoint. |
"renewal <id> is not awaiting DNS verification" |
Verify & Complete on a parked DNS-01 order that already completed, failed, or was cancelled — often the Hub's own 30-second watchdog finished it first. | Re-read the drawer; if the renewal failed, Renew Now starts a fresh order (the record values change). |
| "no active Scout agent serves this endpoint" / "no active Scout agent found for this endpoint" / "no scout assigned to this endpoint" | A live-Scout lookup (Renew, Scan now, Revoke, Adopt key, and friends) found no active Scout at click time. | Check the Scout on Scouts — restart or re-enroll it, then retry. |
"scout is not active" / "scout is not suspended" / "agent is not active (status: <status>)" |
A Scout enable/disable (or + Add endpoint) raced a status change on the agent. | Re-read the Scout's current status and re-issue the intent that still applies. |
| "this endpoint is already in the fleet" | + Add endpoint for a hostname:port that already has a serving row. | Use the existing row — adopt or renew it there. |
"<hostname> could not be reached to verify its certificate" |
Adding a host under a wildcard runs a live probe first, and the probe failed (DNS or connection). | Fix reachability from the Hub, or correct the hostname, then retry. |
Pre-flight refusals also arrive as 409
A refused renewal answers 409 too, with the body
pre-flight refusal: <codes> — but unlike the staleness class above it
will repeat on every retry until the cause is fixed, which is why
the dashboard surfaces it on the button instead of absorbing it. Look
the code up in the family tables above.
Where to next¶
- Renew through a third-party CA — the full renewal flow, including the refusals you expect to meet on the way.
- Adopt a private key — the remedy for the
key_reuse_adoptablerefusal. - Key reuse and pinning — why reuse refuses instead of rotating.
- One certificate on two servers — the full walkthrough behind the replicated-certificate refusals above.