fix(service): diagnose 1053 as a handshake, not a bad config #16

Merged
whitlocktech merged 1 commits from fix/service-start-diagnosis into edge 2026-08-07 18:52:55 +00:00
Member

What & why

Every failed sc.exe start was reported the same way:

sc.exe start RunicGatewayLink failed with exit code 1053. Check the Windows event log; a service that exits immediately usually cannot read its config: C:\ProgramData\RunicGateway\sidecar.toml

For the one error code that actually occurs, that sends the reader to inspect a file that is almost certainly fine.

1053 is not a crash. It is the SCM giving up after 30 seconds waiting for the service process to call StartServiceCtrlDispatcher and identify itself. The process started, ran, and was very likely serving traffic — sc query shows SERVICE_EXIT_CODE : 0, and the same binary with the same config runs perfectly in the foreground. A sidecar older than the one that speaks the SCM protocol produces this every time, on a perfectly good config.

See link#29 for the underlying fix.

What changed

sc.exe start failures now go through windows_start_failure(), which names the actual cause per code:

  • 1053 — a handshake failure, not a crash. Almost always a sidecar older than v1.2.0. Says how to check the version, and how to prove the binary is healthy by running it in the foreground with the same --config.
  • 1069 (ERROR_SERVICE_LOGON_FAILED) — the account is the virtual one the SCM creates itself and has no password, so this is a local policy forbidding virtual service accounts rather than a bad credential. Points at INSTALL.md Appendix A4.
  • anything else — does not guess. Hands over the event log, sc query <name> for the service's own exit code, and the foreground command.

The function is pure and tested on both platforms, like windows_bin_path above it, so the text is covered on the Linux CI runner that never sees an SCM.

Note on MIN_SERVICE_SIDECAR

The 1053 message names v1.2.0 as the floor. That is the version link#29 is expected to release as (current is v1.1.1, and a feat: bumps the minor). If that release lands under a different number, this constant and the matching line in INSTALL.md need updating. Nothing enforces the floor — a version gate on an installed binary would refuse deployments that are working, and the Linux side has no such floor at all.

How it was tested

cargo test — 140 unit + 9 integration passed, including three new cases:

  • error_1053_is_diagnosed_as_a_handshake_not_a_bad_config — asserts the old sentence is gone, and that the message names both the version check and the foreground command. This is the regression guard.
  • a_logon_failure_points_at_policy_not_a_password
  • an_unrecognized_code_still_says_how_to_see_the_real_error

cargo fmt, cargo clippy --all-targets clean.

The message itself was produced by a real failing install on Windows before the fix, and the corrected diagnosis matched what the event log actually said.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.

AI-assisted contributions (required)

  • AI tools were used. Tool(s): Claude Code (Opus 5). I have reviewed and understand
    every change, and take responsibility for it. AI-authored commits are
    marked with a Co-Authored-By trailer.

License

  • I agree that my contribution is licensed under this project's license
    (GNU GPL v3.0 or later), and I have the right to contribute it.
## What & why Every failed `sc.exe start` was reported the same way: > `sc.exe start RunicGatewayLink` failed with exit code 1053. Check the Windows event log; **a service that exits immediately usually cannot read its config**: `C:\ProgramData\RunicGateway\sidecar.toml` For the one error code that actually occurs, that sends the reader to inspect a file that is almost certainly fine. **1053 is not a crash.** It is the SCM giving up after 30 seconds waiting for the service process to call `StartServiceCtrlDispatcher` and identify itself. The process started, ran, and was very likely serving traffic — `sc query` shows `SERVICE_EXIT_CODE : 0`, and the same binary with the same config runs perfectly in the foreground. A sidecar older than the one that speaks the SCM protocol produces this **every time, on a perfectly good config**. See `link#29` for the underlying fix. ## What changed `sc.exe start` failures now go through `windows_start_failure()`, which names the actual cause per code: - **1053** — a handshake failure, not a crash. Almost always a sidecar older than **v1.2.0**. Says how to check the version, and how to prove the binary is healthy by running it in the foreground with the same `--config`. - **1069** (`ERROR_SERVICE_LOGON_FAILED`) — the account is the virtual one the SCM creates itself and has no password, so this is a local policy forbidding virtual service accounts rather than a bad credential. Points at INSTALL.md Appendix A4. - **anything else** — does not guess. Hands over the event log, `sc query <name>` for the service's own exit code, and the foreground command. The function is pure and tested on both platforms, like `windows_bin_path` above it, so the text is covered on the Linux CI runner that never sees an SCM. ## Note on `MIN_SERVICE_SIDECAR` The 1053 message names `v1.2.0` as the floor. That is the version `link#29` is expected to release as (current is v1.1.1, and a `feat:` bumps the minor). **If that release lands under a different number, this constant and the matching line in INSTALL.md need updating.** Nothing enforces the floor — a version gate on an installed binary would refuse deployments that are working, and the Linux side has no such floor at all. ## How it was tested `cargo test` — 140 unit + 9 integration passed, including three new cases: - `error_1053_is_diagnosed_as_a_handshake_not_a_bad_config` — asserts the old sentence is *gone*, and that the message names both the version check and the foreground command. This is the regression guard. - `a_logon_failure_points_at_policy_not_a_password` - `an_unrecognized_code_still_says_how_to_see_the_real_error` `cargo fmt`, `cargo clippy --all-targets` clean. The message itself was produced by a real failing install on Windows before the fix, and the corrected diagnosis matched what the event log actually said. ## Checklist - [x] I have read [CONTRIBUTING.md](CONTRIBUTING.md). - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. ## AI-assisted contributions (required) - [x] AI tools were used. Tool(s): `Claude Code (Opus 5)`. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a `Co-Authored-By` trailer. ## License - [x] I agree that my contribution is licensed under this project's license (**GNU GPL v3.0 or later**), and I have the right to contribute it.
wtclaude added 1 commit 2026-08-07 18:51:34 +00:00
fix(service): diagnose 1053 as a handshake, not a bad config
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m2s
b7d1bbbc78
Every failed `sc.exe start` was reported with "a service that exits immediately
usually cannot read its config", which for the one error code that actually
occurs is the wrong place to look. 1053 is the SCM giving up after 30 seconds
waiting for the process to identify itself; the process started fine and is
very likely serving traffic. A reader who follows the old sentence goes and
stares at a config file that is correct.

Replace it with windows_start_failure(), which names the real cause per code:

- 1053: a handshake failure, almost always a sidecar older than v1.2.0 (the
  first release that speaks the SCM protocol). Says how to check the version,
  and how to prove the binary is healthy by running it in the foreground.
- 1069: the virtual service account was refused, which is local policy rather
  than a bad credential, and points at INSTALL.md Appendix A4.
- anything else: does not guess, and hands over the event log, `sc query` for
  the service's own exit code, and the foreground command.

Pure and tested on both platforms, like windows_bin_path above it, so the text
is covered on the Linux CI runner that never sees an SCM.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit 7771e2e68d into edge 2026-08-07 18:52:55 +00:00
whitlocktech deleted branch fix/service-start-diagnosis 2026-08-07 18:52:56 +00:00
Sign in to join this conversation.
No description provided.