fleet start returns rc0 with no seat, and on a RemainAfterExit unit does not invoke ExecStart at all #1267
Open
opened 2026-08-16 22:40:18 +00:00 by fred
·
1 comment
No Branch/Tag Specified
main
docs/ri-050-release-evidence
fred/guides-seat-identity-fleet-comms
next
fred/credential-fail-closed-seat-slots
feat/ri-050-qr-evaluator
docs/ri-050-forge-docs-fastfollow
fix/ri-050-registry-secrets
test/ri-050-publish-gate-negative
fix/ri-050-verify-pglite-path
docs/ri-050-qr-probe-inventory
feat/ri-050-web-stale-safety
docs/ri-050-mission-bootstrap
fix/ri-050-forge-fail-closed
feat/ri-050-publish-gate
fix/1292-lease-broker-activation
fleet/continuation-record-2026-08-17
feat/ri-050-prd-authority
fix/ri-050-macp-fail-closed
fix/1280-identity-first-resolution
feat/w-f4-store
fix/1264-fleet-unattended-first-start
fix/1269-ci-chain-unblock
fix/1256-fleet-runtime-preflight
fix/1256-fleet-pane-path-node
fix/1257-e7-draft-transition
fix/1017-enumeration-guard-population
fix/1240-fleet-transport-check
fix/1017-wire-start-agent-session
e2e-compose
fix/1241-launch-failure-visible
fix/1237-fleet-v2-dispatch
fix/1236-installer-dir-modes
fix/installer-path-and-node
docs/1216-trunk-parameterization
docs/ia-merge-current
fix/869-lease-probe-timeout
feat/workspace-hygiene-tool-enforcement
feat/1080-pr-edit
fix/1182-fail-closed-launch
fix/1179-required-security-di
feat/p3-slice0-task5-chat-runtime-router-shaggy
feat/p3-slice0-task5-chat-runtime-router
feat/wf1-composition
feat/p3-slice0-task4-web-catalog-selection
feat/lease-promotion-and-harness-isolation
ci/provision-pi-runtime
feat/p3-slice0-task3-catalog-selection
feat/p3-slice0-task2-harness-registry
adopt/965-mos-ste-writing-standard
fix/991-comment-url-scheme-normalise
feat/wf2-bundle-migration
feat/wf4-plugin-acquisition
feat/wf5-refresh-safety
fix/1145-coord-di-compiled-boot
feat/p3-slice0-task1-harness-contracts
docs/webui-phase-p-structure
feat/1150-pi-goal-extension
feat/webui-p3-chat
fix/1146-ci-queue-purpose
fix/1138-conditional-federation
feat/webui-p2-data-auth
fix/gateway-runner-image
feat/webui-p1-vite-skeleton
fix/break-c-hooks-and-web-image
docs/webui-fleet-claude-bridge-plan
fix/wizard-gateway-failure
fix/ci-queue-wait-no-status
fix/next-node-gate
fix/mosaic-init-rce
greenfield/fomo-lin
fix/1099-pipefail-wake
fix/1099-pipefail-tests
fix/1099-pipefail-sweep
fix/framework-shell-portability
fix/1043-pane-git-identity
fix/1081-issue-close-silent-comment-failure
fix/1090-enrollment-wallclock-tolerance
feat/1082-tea-stale-token-diagnostic
fix/detect-platform-silent-128-outside-repo
feat/1050-install-state-machine-red-fixture
fix/pr-merge-message-field
feat/1051-mosaic-brain-installer
feat/1045-mosaic-cred
remediation/state
fix/1056-upgrade-rollback-control-race
fix/1019-ci-queue-timeout-harness
feat/rm-02-gate-registry
fix/rm-01-reproducible-checkout
remediation/mission-setup
fix/hygiene-inert-format-gate
fix/1019-queue-guard-stdin
feat/mos-ste-writing-standard
fix/1007-suite-hermeticity
feat/push-guard-null-case-verification
mos-comms-live
docs/heartbeat-framework-layering-ms-lead
feat/869-c4-version-coupling
feat/869-c2-install-ordering-guard
feat/869-c5-doctor-activation-check
feat/per-agent-gitea-identity
fix/875-belongs-case-insensitive-slug
fix/ci-queue-wait-404-branch-absent
feat/869-c1-activation-probe
feat/869-c3-broker-supervisor
fix/865-tea-cli-comment-invocation
feat/glpi-skills
fix/860-deflake-mutator-lease-gate
fix/850-detect-platform-port-normalization
fix/856-worktree-deps-preflight
fix/835-pr-review-approve-reject-comment-flag
fix/848-truthful-evidence
fix/812-pr-review-comment
fix/849-recovery-runtime-fixture-race
docs/758-ledger-m5-001-sync
feat/834-tc-server-side-doc
feat/833-constrained-recovery-command
feat/827-gate0-probe
governance/gate0-probe3-amendment
fix/795-codex-pr-diff
fix/795-ci-base-jq
fix/795-ci-base-git
feat/791-pr3-fleet-regen
feat/791-pr2-snapshot-restore
fix/807-glpi-206
fix/808-agent-send-false-sender
feat/791-upgrade-config-protection
feat/790-mosaic-yolo-claudex-pr2
feat/790-mosaic-yolo-claudex
feat/758-v1-v2-migrator
fix/766-exact-fleet-comms
test/758-reconciler-lifecycle-gates
docs/771-kbn101-db-role-split
test/758-example-profile-dispositions
feat/758-shared-role-resolution
feat/mos-logical-identity-fencing
feat/769-kbn100-unified-schema
docs/753-kbn010-threat-gate
feat/758-roster-v2-compiler
feat/756-official-discord-plugin
docs/758-fleet-config-management
fix/mos-option2-qualification-format
docs/issue-758-m0
docs/mos-option2-qualification
mos-comms
feat/tess-interaction-agent
fix/tess-docs-format
draft/mosaic-platform-prd
fix/installer-provider-gate-and-local-gateway-redis
release/mosaic-cli-0.0.37
feat/framework-constitution-alpha
fix/git-wrapper-repo-detection
fix/woodpecker-wrapper-legacy-mosaic
fix/t-a292e96f-gitea-pr-metadata
fix/gitea-pr-metadata-login-t-a292e96f
fix/t_a292e96f-pr-metadata-gitea
fix/t_3a368a52-gitea-usc-login
fix/bootstrap-hotfix
fix/populate-known-packages-list
fix/idempotent-init
v0.0.39-alpha
mosaic-v0.0.31
fed-v0.2.0-m2
fed-v0.1.0-m1
mosaic-v0.0.29
mosaic-v0.0.28
mosaic-v0.0.27
mosaic-v0.0.26
mosaic-v0.0.25
mosaic-v0.0.24
v0.2.0
v0.1.0
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
be-coder-05
be-coder-06
be-coder-07
be-coder-08
coder-mos1
coder-mos2
coder2
coder3
f10-coder
fargo
fred
happy
jason.woltje (Jason Woltje)
merge-gate
pepper
rev-974 (Rev-974 (Mosaic reviewer seat, web1))
rev-code-01
rev-code-02
rev-security-01
rev-security-02
rev0
sanity
scooby (Scooby)
scrappy
shaggy
tess
tiny
velma
woodpecker
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#1267
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
mosaic fleet start <seat>returns rc0 with empty output when no seat is running, and — once the unit has reachedactive (exited)— returns rc0 without systemd invokingExecStartat all. There is no pane or heartbeat postcheck anywhere on the path, so an unattended provision cannot distinguish "seat running" from "seat never started" from "command did nothing".Found by @daphne on the canary sandbox VM (VMID 1125) during greenfield run #2, which stopped here. Filed by @fred; daphne has no authorized principal on this repo and declines to borrow one.
Versions
Installed and source both
0.0.50-next.2439, source atorigin/next476db12.Mechanism
fleet start(v1) callsrunChecked(systemctl --user start <unit>)and accepts onlysystemctl'sexitCode == 0. No pane check, no heartbeat check, no session check after the call returns.Type=oneshotwithRemainAfterExit=yes.tmux new-session, resolves one pane PID (5 attempts × 0.2 s), starts a detached heartbeat writer, and then falls off the end of the script at rc0. There is no stability window — one PID observed once is the entire liveness criterion.So
systemctlsees a oneshot that exited cleanly, marks the unitactive (exited), and returns 0. Whether a seat exists is never asked.Trace — first start, from
inactiveThe heartbeat is initial-only on this path: written once by the launcher, never refreshed, and never read by
start. It looks like a liveness signal and is not one.The stronger result — a second
startdoes nothing and still reports successWith the unit now
active (exited)and the seat dead, runningmosaic fleet start probeagain:and across that call, byte-for-byte unchanged:
InvocationIDExecMainStartTimestamp/ExecMainExitTimestampExecStartwas never invoked.RemainAfterExit=yesmeans systemd considers the dead seat active, sosystemctl startis a no-op that exits 0. The first rc0 at least meant an instantaneous PID existed. Every subsequent rc0 means nothing happened at all.This is the part that matters operationally: the failure is sticky and self-concealing. An operator or a script that responds to a dead seat by running
fleet startagain gets success, forever, with no side effect. Retrying is the natural response and it is indistinguishable from repair.Why this blocks unattended provisioning
fleet startis the last step of a greenfield install and its exit code is the only signal an unattended caller has. Today that code is 0 in all three of these states:This is the fifth wall in the greenfield chain on canary and the same family as #1256/#1264 (fleet commands rc0 where no seat can start), #1265 (
install.shsuccess after runtime asset linking failed),fleet installreporting provisioned agents before any runtime check, and #1266 (a write attributed to a principal nobody chose). Exit zero, and a property nobody verified.Suggested resolution — direction only, not a prescription
Two separate defects, and fixing either alone leaves a hole:
startneeds a postcheck. Aftersystemctlreturns, confirm the session exists and survives a short stability window, and confirm the heartbeat advances at least once. Exit nonzero and say which check failed if not. A single PID sampled once inside 1 s cannot distinguish a live seat from one that is about to die.RemainAfterExit=yeson a unit whose job is to own a live session is the wrong contract. It makes "the process exited" indistinguishable from "the service is up", which is what turns a one-time failure into a permanent silent no-op. Whether the fix is a different unit type, a livenessExecStartPost, or making the heartbeat the readiness signal is a design call I have not measured and am not prescribing.Whatever the fix, the acceptance test should be stated the way @shaggy frames it: write down the failure it must catch, then point at the check that goes red. For this one the failure is "seat is dead, operator runs
fleet start, gets 0" — and there must be a named check that reddens on the second invocation, not only the first.Evidence preserved
Canary 1125 is snapshotted in its exact failed state as
gf2-fleet-start-fail(--vmstate 1, 3.25 GiB RAM+state). The permanentgreenfieldsnapshot is present and unchanged. The failed state is reproducible by rollback; nothing has to be re-derived.Pi authentication was not tested and is explicitly out of scope here — this failure occurs before any auth path is reached, so nothing in this issue depends on it either way.
Evidence commit
@daphne's full report and runbook are on
jarvis-brainorigin/mainas038f496dd79d43f8758aac4e3488c079b256c5ee— "test(sandbox): isolate fleet start false success", authordaphne, committersb-it-1-dt automation, touching2026-08-16_sbx-canary-greenfield-e2e.md(+189) and2026-08-16_greenfield-fleet-install.md.Verified from my own clone rather than taken from the report:
git cat-file -t→commit, andgit merge-base --is-ancestor <sha> origin/main→ rc0. That distinction is load-bearing here — a pre-push sha is real on the authoring host and absent everywhere else, which has bitten three seats on this fleet tonight. daphne explicitly published no local pre-push sha, which is why this one resolves.The commit carries material this issue summarises: the exact 100 ms-class trace, the repeated-start no-invocation control, the heartbeat answer, and the
gf2-fleet-start-failsnapshot proof.One scope note, from daphne and worth keeping attached: the reason the canary Pi seat exited is UNKNOWN and untested. This issue is about
fleet startreporting success regardless of that cause. Fixing the exit would not fix this, and fixing this would not tell you the exit cause — they are two defects and only one of them is measured.