Dialog
Codes
Every user-facing failure carries a stable SGXXXX code. Codes never change
meaning, so a script can match on them and each has a permanent anchor on this
page. A diagnostic's docs link points straight at its code here.
General
SG0001
Catchall — a failure that has no more specific diagnosis yet.
SG0002
Persisted cron history or active-run state could not be restored. The scheduler
may continue without reliable history; inspect the supervisor log and the
project's cron_state.xml before deleting anything.
SG0003
A cron unit could not be registered without conflicting with existing scheduler state. Reload the owning project after the active mutation finishes.
SG0004
A finite unit that exited successfully was recorded as failed or stopped. The process completed its work; the persisted lifecycle state is inconsistent.
SG0005
The supervisor is using an outdated or different project manifest. Resubmit the
intended file with -c <path> before mutating the project.
SG0007
The supervisor cannot safely restart or transfer ownership while another operation controls its runtime. Let the named operation settle, then retry.
SG0008
A service failed to start without a more specific diagnosis. Read the attached
reason and service logs; specific failures use
SG0102–SG0110
instead.
SG0009
Persisted service state disagrees with the live process table. Use
sysg status --live to refresh runtime evidence before taking action.
SG0010
The requested service log source is unavailable or points at the wrong runtime scope. Confirm the project selector and configured log sink.
SG0011
A live log-follow stream became stale or could not reconnect to its project.
The workload may still be running; check sysg status before stopping it.
SG0012
Log output exceeded a safe storage or display bound. Narrow the query with
--lines, --since, or --grep, or adjust configured rotation limits.
SG0013
A daemonized service inherited an environment that systemg cannot safely
reproduce. Review its env, privilege, and session-variable settings.
SG0014
The installer could not obtain or verify the expected release artifact. The active version remains unchanged.
SG0015
Supervisor IPC, PID files, or tracked process ownership disagree. Avoid manual PID-file edits; inspect live status and the supervisor log before recovery.
SG0016
A rolling deployment failed without a more specific health, switch, or process diagnostic. The previous instance is retained when systemg can do so safely.
SG0017
logs --prune was run with no --max-size or --max-age bound, so there is
nothing to prune against. Pass at least one bound.
SG0019
sysg logs ran with no -s, -p, or --supervisor, so there is no target to
read. Logs are always scoped: pass -p <project> (a whole project), -s <service>
(a loose service, or -p <project> -s <service>), or --supervisor.
SG0020
logs --supervisor was combined with a -s/-p selector. The supervisor's own
log is a single stream; drop the selector, or drop --supervisor to read a
service's logs.
SG0021
logs -s <service> (with no -p) named a service that is not in the loose
bundle. A bare -s reads only __loose__; if the service belongs to a project,
pass -p <project> -s <service>.
Start
SG0101
A cron unit was targeted by a direct start or restart. Cron units are
schedule entries rather than persistent services: inspect the failed run, fix
its cause, and wait for the next scheduled run. Restarting the owning project
reloads its schedule but does not trigger an immediate run.
SG0102
A service exited immediately at start, before it finished starting.
SG0103
A service's pre_start command failed, so the service was not started.
SG0022
A service's health check could never reach it — every probe failed to connect
(HTTP connection refused / DNS failure) or the health command could not run. The
address may be wrong or nothing is listening on the port. When total_timeout
is configured, probes continue for that full readiness window before this error.
SG0023
A service's health check timed out — a probe did not complete within its
attempt_timeout. The endpoint accepted the probe but was too slow to answer
within the per-attempt budget before its retries and total readiness window were
exhausted.
SG0104
A service's health check ran and reported the service is not healthy (an HTTP non-2xx response, or a health command that exited non-zero).
SG0105
A service exited at start because it could not bind its port — something else is already listening on it. The diagnostic names the port when the service's output reveals it. Stop whatever holds the port, or change the port in the service's command.
SG0106
A project was registered with a running supervisor, but one or more of its services never came up.
When a supervisor is already resident, sysg start hands it the project and the
supervisor boots it on a background thread — which keeps a slow boot from
blocking every other command. The start waits for that boot to settle and
reports this code when services are left stopped or failed, so a start that did
not work cannot exit 0. The diagnostic names each service and gives you the
sysg logs command for it; the underlying cause
(SG0103 pre-start failure,
SG0104 health check,
SG0105 port in use) is in that service's
log.
SG0107
Reserved, and no longer emitted. It reported the supervisor as having refused a command because it was busy with another mutation. That was never what happened: mutations are queued onto the owner thread, not rejected, so a command this code blamed had in fact been accepted, and a long restart that outran the client's wait went on to finish while the CLI called it unapplied.
The two things it conflated are now reported separately —
SG0111 when the supervisor is answering
and still working, and
SG0205 when it has stopped answering at
all. The code is kept so a published diagnostic is not withdrawn.
SG0108
A service's pre_start command exceeded the pre_start_secs budget from
supervisor.xml. systemg terminated the command tree and did not launch the
service. Restore the resource the command was waiting for, increase the budget
when the command legitimately needs longer, then start the project again.
SG0109
A service was not started because a declared dependency did not reach its
required running or completed condition. Resolve the dependency's earlier
diagnostic first; downstream services remain stopped rather than starting into
an invalid dependency state.
SG0110
Automatic restarts for a service were stopped because it exhausted its restart budget without ever staying up. The breaker opens when a unit either burns its whole budget inside a 15-minute window or never survives 60 seconds across that many consecutive attempts — reaching a running state and dying seconds later counts as a failure, not a success.
The budget defaults to 8 attempts and is overridden per service with
max_restarts. Backoff grows exponentially from the configured backoff, up to
five minutes.
There is no automatic retry after the breaker opens: restarting a unit that has
failed identically N times only repeats the failure. Fix the underlying cause,
then re-arm it explicitly with sysg restart --service <name> --project <id> —
an explicit start or restart is the only thing that clears the breaker.
SG0111
The supervisor is answering its control socket and is still working on the command, but has not finished within the client's budget. The command was accepted and keeps running — only the wait was abandoned, and nothing about this cancels it.
Everything except a cached status, version, current-op and inspect is
queued onto the single owner thread and answered when it completes, so the wait
is as long as the work: restarting a project of twenty units with health checks
legitimately runs for minutes. The client waits for as long as the supervisor
keeps answering, up to a backstop that defaults to 15 minutes — a deadlocked
owner thread would otherwise hang the CLI forever, since the socket stays
responsive either way.
Raise or remove the backstop with timeouts.command_wait_secs in
supervisor.xml, where
0 waits indefinitely. sysg status shows what the operation is doing.
Selectors, status & stop
SG0006
A bare -s <name> selector matched a service in more than one loaded project, so
the target is ambiguous. Pass -p to choose the project.
SG0201
The -p project does not match the config sysg resolved.
SG0202
The command names a service or project that does not exist.
SG0203
A config file could not be found or read.
SG0204
Mutually exclusive selectors were combined (e.g. --supervisor with -s/-p,
or two logs modes).
SG0205
The supervisor's process is alive but not answering its control socket. Raised
before a command is sent, it was refused rather than routed into a dying daemon.
Raised while one is in flight, the supervisor stopped answering after taking it,
so whether it was applied is unknown — check sysg status once the daemon is
back rather than assuming either way.
SG0206
No supervisor is running, so status reports state read off disk; any processes
still alive are unsupervised orphans.
SG0207
An !included file is missing, unreadable, or not valid YAML; the diagnostic
carries the include chain from the root manifest to the broken fragment.
SG0208
A manifest's includes form a cycle, so assembly was refused.
SG0209
Includes nest deeper than 10 levels or exceed 8 MiB of cumulative fragment content, so assembly was refused.
SG0210
A manifest field holds a value systemg cannot interpret, so the manifest was
refused before anything started. The diagnostic names the field's dotted path
(e.g. services.db.deployment.health_check.interval) and the value it rejected.
Durations are a whole number with an optional unit — ms, s, m, or h
(100ms, 2s, 5m, 1h). A bare number is seconds, so 15 and 15s are the
same value. Fractions (0.5s) are not accepted; write them in a smaller unit
(500ms). A health check's interval must also be greater than zero.
Restart
SG0301
A restart's new manifest is invalid, so the restart was refused and nothing changed.
SG0302
A restart ran but left one or more units short of their target state.
SG0303
A supervisor recycle stopped the old daemon but the new one did not come up.
Purge
SG0401
A purge was refused because a live supervisor is still managing processes; stop
it or pass --force.
SG0402
A purge removed some state but hit an IO error before finishing, so the on-disk state may be partial.
SG0403
A scoped purge named a project that has no state on disk; nothing was deleted.
SG0404
A purge target did not name a single project directory. A project id is one path segment: an empty id resolves to the projects root and a traversing or absolute id escapes it, so either would delete more than the target named. Every target is resolved before the first deletion, so nothing was deleted.
SG0405
A purge was refused because the resident supervisor did not exit after a shutdown request. Deleting the state and socket out from under a live supervisor would leave it running as an unreachable orphan (root-owned in system mode), so nothing was deleted. Inspect the supervisor process and stop it before retrying.
Upgrade
SG0501
The staged upgrade target is not a trusted sysg executable. The file may be missing, non-executable, writable by another user, or unable to report valid live-upgrade metadata. The resident supervisor and its workloads are unchanged.
SG0502
The staged binary is not live-reexec compatible with the resident supervisor.
Live upgrades require a strictly newer target with the same protocol and
handoff schema. Residents from 0.56.0 through 0.57.0 also require the target
to remain on their major/minor release line; earlier residents do not support
live re-execution.
The resident, its workloads, the PATH target, and the active-version record are left unchanged. To accept the brief interruption and activate the installed target:
$ sysg stop --supervisor
$ curl --proto '=https' --tlsv1.2 -fsSL https://sh.sysg.dev/ | sh
Stopping the supervisor stops every registered project. Restart each required project from its manifest after installation. See the full compatibility and recovery path.
SG0503
The supervisor cannot currently reach a stable handoff point. A project may still be booting, a cron run or deployment may be active, or another runtime mutation may own the control plane. An unresponsive supervisor, dynamic child, or non-transferable log stream can also block the handoff. Retry after the named condition settles.
SG0504
The resident supervisor validated the target but could not serialize its state or execute the replacement binary. It resumed normal operation without releasing workload ownership.
SG0505
The replacement binary started but could not restore the handed-off runtime. systemg attempted to re-execute the previous binary; inspect the supervisor log before retrying the upgrade.
Migration
SG0601
Legacy __loose__ state is present and has not been migrated. Project-less
manifests each own a project derived from their path; state written under the
old shared __loose__ project predates that and must be placed before those
manifests can be managed separately.
SG0602
A state migration was refused because a supervisor is running. The migration
moves the files a live supervisor is reading and writing, and boot loads state
before it takes the supervisor lock, so there is no lock that would make it
safe. Stop the supervisor first. --dry-run is always allowed.
SG0603
Legacy state could not be attributed to exactly one manifest, so it was archived rather than assigned. A state row carries only a service name; when several manifests declare that name, nothing distinguishes them. The migration never guesses — the archived copy is reported so it can be placed by hand.
SG0604
A previous state migration did not finish, so the layout is part legacy and part
migrated. Re-run sysg migrate-state to resume from the recorded phase.
SG0605
A migrated artifact did not match the checksum recorded when it was archived. Nothing was removed; re-run the migration to retry.
System mode
SG0701
Running as root without --sys. State would be stored in root's user-mode
paths (~/.local/share/systemg), not the system runtime at
/var/lib/systemg. If the system runtime is the target, re-run the same
command with --sys.
SG0702
On-disk state belongs to the other runtime mode than the one this command
targets. Most commonly: system-mode state exists at /var/lib/systemg but the
command ran as root without --sys. systemg refuses rather than target the
wrong runtime; add --sys (or drop it) so the mode matches the state.
SG0703
System-mode integration is broken: the installed systemd unit or launchd job is missing, points at a different binary, or predates the installed version. Re-run the installer to regenerate it.
SG0704
--sys targets the root-owned system runtime and requires root privileges.
Re-run under sudo, or drop --sys to operate on the per-user runtime.
Container-init and sandboxing
Codes emitted by sysg init (container PID 1) and by kernel-enforced
sandboxing. The last three are reserved: they have no callsites, and are
listed so their anchors and meanings stay stable if kernel-assisted
observation ever ships.
SG0711
Container-init was requested where it cannot work: sysg init on a non-Linux
platform, or in a process that is not actually PID 1. Run it as a container's
ENTRYPOINT (without Docker's --init flag, which installs its own init).
SG0712
PID 1 prerequisites are missing: procfs is not mounted at /proc, or init is
not running as root. Fix the container image or runtime flags and retry.
SG0713
PID 1 shutdown incomplete: one or more services survived reverse-order teardown, so init exited nonzero rather than pretend the container wound down cleanly. The surviving units are named in the log.
SG0714
Live supervisor upgrade is forbidden in container-init mode: a failed exec in PID 1 kills the container and every service in it. Upgrade the container image instead.
SG0721
A security key was accepted by the schema but cannot be enforced, so the
service runs unprotected. The diagnostic names the exact key:
apparmor_profile, selinux_context, private_devices, or private_tmp. A
future release refuses these keys instead of warning, behind a manifest schema
bump.
SG0722
A seccomp filter could not be built, compiled, or applied. systemg refuses the service rather than run it without the requested syscall filter.
SG0723
prctl(PR_SET_NO_NEW_PRIVS) failed, so seccomp and Landlock cannot be applied
safely. The service is refused.
SG0724
A landlock filesystem sandbox was requested (schema v3) but the kernel does
not support Landlock (needs Linux 5.13+) or could not fully enforce the
ruleset. systemg refuses the service rather than run it unconfined. Run on a
Landlock-capable kernel, or remove the isolation.landlock block.
SG0725
The manifest named a seccomp profile that does not exist. The only built-in is
baseline-v1, a frozen deny-by-default allowlist. Checked in the parent, so
the spawn is refused before fork.
SG0726
seccomp is only supported on x86_64 and aarch64. On any other architecture a
manifest requesting isolation.seccomp is refused rather than run unfiltered.
SG0727
A namespace listed under isolation could not be unshared. EPERM and
EINVAL are tolerated — a nested container often refuses namespaces the
service runs fine without — so this code means the kernel failed the request
for some other reason and the service is refused.
Privilege drop
Codes emitted while a service's child process takes on its configured
identity, between fork and exec. Each one means the service was refused
rather than started with more privilege than it asked for.
SG0741
A resource limit (nofile, nproc, or memlock) could not be set.
SG0742
The scheduling priority from limits.nice could not be set.
SG0743
The CPU set from limits.cpu_affinity could not be applied — usually a CPU
index that does not exist on this machine.
SG0744
The supplementary group list could not be installed. The service is refused: starting it would leave it holding the supervisor's groups.
SG0745
The primary group could not be switched to the configured group.
SG0746
The user could not be switched to the configured user. The service is
refused rather than run with the supervisor's identity.
SG0747
The capabilities listed under capabilities could not be retained across the
identity switch, so the service would have started without them.
SG0748
Capabilities could not be fully dropped, so the service would have kept more privilege than it was configured with.
SG0731
Reserved — kernel-assisted observation is required by configuration but unavailable; start refused with the missing prerequisites as evidence.
SG0732
Reserved — kernel-assisted observation unavailable; degraded to polling.
SG0733
Reserved — kernel-assisted event loss; a /proc reconciliation pass would be
forced.
SG0705
The manifest declares root-only keys (user, group, capabilities,
limits.cgroup, isolation, non-empty supplementary_groups) and was
validated against — or started in — user mode, which cannot enforce them.
Validate against the system runtime with sysg validate --sys (no root
needed), start with sudo sysg --sys start, or remove the keys.