Skip to content

fix: report macOS service inspection failures instead of a stopped state - #60

Merged
krisiasty merged 1 commit into
mainfrom
fix/macos-status-errors
Oct 15, 2026
Merged

krisiasty merged 1 commit into
mainfrom
fix/macos-status-errors

Conversation

@krisiasty

Copy link
Copy Markdown
Owner

Pull request

Summary

On macOS, Status ran launchctl list <label> and parsed its output only when the command succeeded; every failure returned a status that looked like a stopped service, with no error. Timeouts, a missing launchctl, and permission or domain errors were all discarded, so callers acted on a state nobody had observed.

  • Only launchctl's "Could not find service" exit status (113) now means the job is not loaded and therefore not running. This was confirmed against the real launchctl list for an unknown label.
  • A timeout is reported as launchctl list … timed out after 15s, and every other failure is returned with launchctl's own output.
  • Output parsing is unchanged; malformed output was already reported as an error.
  • A shared launchctlNotFound helper replaces the exit-status check that kickstart (fix: restart the macOS service in one launchd operation #58) used.

Effect on callers: -restart stops on an inspection failure instead of acting on a guessed state; -reload reports the real error instead of "not running"; -status returns the error instead of printing a misleading state; -diag already reported Status errors as failures and now shows the real cause. The Linux implementation already propagated errors this way.

Reporting "installed but not loaded" as a separate state, also suggested in #52, is left to #51, which covers recovering exactly that case.

Closes #52.

User impact

macOS lifecycle and status commands fail with the real launchctl error instead of reporting a stopped service when launchd cannot be inspected. A job that is simply not loaded is still reported as installed and not running.

Validation

  • Unit tests against a fake launchctl: running job; unloaded job (exit 113) reported as stopped without error; launchctl failure, timeout, missing executable, and malformed output each reported as errors without claiming the job is running; restart does not kickstart after an inspection failure. The fix: restart the macOS service in one launchd operation #58 restart tests that modeled "not loaded" with exit status 1 now use the real 113.
  • Mutation check in a scratch copy: with failures swallowed again, the failure, timeout, missing-executable, and restart tests fail.
  • Read-only check of the real installed job: Status reports it installed and running with its PID and no error.
  • SSH_AGENT_PROXY_REQUIRE_OPENSSH=1 go test -race ./...; twenty race-enabled repetitions of the launchd tests.
  • Native and Linux golangci-lint (0 issues), go vet ./... (also GOOS=linux), formatting, git diff --check, and CGO-disabled builds for darwin/linux × amd64/arm64.

Checklist

  • Tests cover changed behavior.
  • Documentation is updated when behavior or design changed.
  • No credentials, private configuration, or identifying key metadata are included.
  • go test -race ./... passes locally, or the reason it was not run is documented.

🤖 Generated with Claude Code

Status turned every failed "launchctl list" into a result that looked
like a stopped service: timeouts, a missing launchctl, permission and
domain errors were all discarded. Restart could then act on a state
nobody had observed, Reload reported "not running", and diagnostics lost
the real cause.

Only launchctl's "Could not find service" exit status (113) now means the
job is not loaded and therefore not running. A timeout is reported as
such, and every other failure is returned with launchctl's output. The
Linux implementation already propagated errors this way.

Closes #52.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@krisiasty
krisiasty merged commit 25749ee into main Oct 15, 2026
11 checks passed
@krisiasty
krisiasty deleted the fix/macos-status-errors branch October 15, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: macOS status silently discards launchctl inspection failures

1 participant