When ensure refuses

ensure refuses

stado service ensure is idempotent and honest: each of its refusals in the field names its own repair.

  • A per-login unit on a headless Mac. The declaration puts the unit in launchd's user domain on a Mac whose recorded console is headless (stado host console record), where macOS's questions to an agent are never answered and, with nobody logged in, launchd builds no gui/<uid>. The finding is printed as one sentence ending in the command that moves the unit (stado service ensure <name> --host <host> --as-daemon --reason …), which stops the agent, reads the daemon until it answers, and only then removes the agent's file. stado service list and stado registry doctor report the same finding before any restart trips over it.
  • A LaunchAgent loaded in the background domain. When the account does not hold a graphical session, a LaunchAgent goes to user/<uid>, and the report says why: <account> does not own /dev/console (it belongs to <owner>), or (it cannot be read (<stat's words>)) when the console's owner could not be read, or <account> owns /dev/console but launchd answers no gui/<uid>. An unreadable console is never reported as one belonging to nobody.
  • A loaded unit running a different program. The refusal reads <domain>/<unit> is loaded and runs [<declared argv>], not [<argv>]; retire it first. launchd holds the definition it bootstrapped, so rewriting the plist under a live job changes nothing an operator can see; ensure refuses rather than silently overwrites. Retire the unit (stado service retire <unit> --host <target>), then ensure again.
  • Registry push refused on directory generation. A registry write replaces the whole document, so a push that would delete top-level keys, or whose service_directory.generation would go backwards (which would make every stale cached directory start looking current), is refused. The refusal spells the repair: re-pull, re-apply the edit, and push again; --force only if the deletion or the older directory is genuinely the intent.
  • Registry push refused because a document does not parse. The push guards compare the uploaded document with the stored one, so both must parse as one document object. A payload that does not is refused with its parse error before anything is written, and a stored registry that does not parse is refused naming its generation; neither --force nor --allow-empty-fleet bypasses this. Repair the file (or the stored object, through stado registry pull and a corrected push) and push again.
  • registry doctor names a product-catalog-unreadable finding. The check for units whose host declares no managed_versions entry reads the compiled product catalog to tell a managed unit from an arbitrary tree. When the catalog cannot be read, the doctor says so for that host, with the catalog's own refusal, instead of reporting the host as having every version declared. Repair the catalog (stado product catalog prints the same refusal) and run the doctor again.
  • registry doctor names a directory-url-unreadable or directory-url-without-port finding. The check that compares a service directory endpoint with its product's stable bind reads the endpoint as a URL and takes the port it names. An endpoint that is not a URL, or names no port, cannot be compared, and the doctor says so for that host and service instead of passing it. Repair the endpoint in the service directory and run the doctor again; directory-names-candidate-port remains the finding for an endpoint that names a rollout's candidate port.
  • registry doctor names a registry-document-drift finding. The doctor parses the registry from one fetched document and then reads the same document's targets entries beside the parsed targets. A parsed target whose entry is missing from that document is reported by name instead of being read as an empty entry; it means the document the doctor holds does not describe the registry it parsed. Fetch the registry again and run the doctor on the fresh document.
  • registry doctor names an unread-declaration finding. A registry target key no reader in the running Stado consults: not modelled by the target type, not catalogued among the declarations read out of raw JSON (targets[].bearers, services, …), and not read by a shipped catalog service through a ${declared:<key>} placeholder (the host process's health_interval_seconds, Weles's weles.recordings_dir). Remove the key, or give it the reader it was declared for. A catalog-unread finding says the catalog's placeholder keys could not be listed; every unmodelled key is then judged without them, so a key only a catalog unit reads appears as unread until the catalog reads again.
  • registry doctor names a unit-env-drift finding. On the machine the doctor runs on, a managed unit's file carries none of a variable its catalog entry's env declares (<unit> (<path>) carries no <NAMES> that its catalog entry <product> declares, so its program starts without them): the unit was written before the entry gained the variable, and nothing rewrote it since. Names are compared, never values. stado service ensure <product> --host <host> writes the unit from the catalog. A unit-env-unread finding names a unit file that exists and cannot be read; another host's units are not compared from here. Stado Desktop's Registry screen runs the same doctor as Compare the registry with every host's live state and name each divergence and its repair, with the command's own receipt.
  • registry doctor names a foreign-install-root finding. A release-controlled product's install_root is an absolute path under one target's home while another target's home differs; release control expands only {home}, so that target's agent installs where it is not at home. stado release policy root repair <product> writes the root as {home}/<rest> (the finding names it) in one verified registry write; --check says what it would write. A new target that placement standby adds rewrites the root itself, and release policy apply refuses a policy whose root lies under one target's home (install_root <root> lies under <host>'s home, so <hosts> would install where they are not at home; write it as {home}/<rest>), so the finding names only documents written before that refusal.
  • registry doctor names a schedule-pinned-nowhere finding. A live schedule is pinned to a consumer no registry target names, by name or by its <kind>-<hostname> identity, so its jobs wait for a claimer that never comes — typically a host that was removed or renamed. Declare it again with stado schedule create --id <id> --converge, its cron and command as before and --pinned-host <host>, or, when its host was emptied onto another, evacuate with --repin-schedules. ambiguous-schedule-pin names a pin an identity two targets claim (once per schedule), and unreadable-schedules a schedule store that did not answer.
  • registry doctor names a profile-lacks-catalog-stores finding. A placement profile does not carry a store the catalog declares for a product it runs (Brama's donated subscriptions, Skarbiec's vault, Weles' keeper), so a move would leave it on the fenced source and placement move refuses the profile. stado placement profile sync <profile> adds what the catalog declares; placement evacuate --standby does it in its run. profile-stores-unjudged names a profile whose units the catalog could not be read against.
  • registry doctor names a service-second-name finding. A host records a unit the product catalog declares (by its unit name or its launchd label, com.wisent.<unit>) under a name that is not the catalog's, such as com.wisent.skarbiec for skarbiec, so the service's supervision state is kept under two names and a reading by the catalog name finds nothing. The finding names the record's path and the one field that moves it: stado registry set --path targets.<host>.services.<index>.name --value <catalog name>, which changes the record's name in the registry and no unit on the host. stado service adopt records a catalog unit under the catalog's name, whatever label it was adopted by, so no new record of this kind is made. --json counts the records compared under checked.service-second-name; service-second-name-unjudged names a catalog that could not be read.

Source: this website