benbjohnson/litestream · critical
failed to connect to control socket: %w
Error message
failed to connect to control socket: %w
What it means
The register command talks to the litestream daemon over a Unix control socket (custom DialContext dialing 'unix' at -socket path, default /var/run/litestream.sock). If client.Post fails — socket missing, daemon not running, socket disabled in config, permission denied, or the -timeout elapsed — the error is wrapped as 'failed to connect to control socket'.
Source
Thrown at cmd/litestream/register.go:74
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.DialTimeout("unix", *socketPath, clientTimeout)
},
},
}
req := litestream.RegisterDatabaseRequest{
Path: dbPath,
ReplicaURL: replicaURL,
}
reqBody, err := json.Marshal(req)
if err != nil {
return fmt.Errorf("failed to marshal request: %w", err)
}
resp, err := client.Post("http://localhost/register", "application/json", bytes.NewReader(reqBody))
if err != nil {
return fmt.Errorf("failed to connect to control socket: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response: %w", err)
}
if resp.StatusCode != http.StatusOK {
var errResp litestream.ErrorResponse
if err := json.Unmarshal(body, &errResp); err == nil && errResp.Error != "" {
return fmt.Errorf("register failed: %s", errResp.Error)
}
return fmt.Errorf("register failed: %s", string(body))
}
var result litestream.RegisterDatabaseResponse
if err := json.Unmarshal(body, &result); err != nil {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Start the litestream daemon and enable the control socket with `socket.enabled: true` in the config, then restart it
- Confirm the socket path: `ls -l /var/run/litestream.sock` (or your -socket value) and pass -socket if it differs
- Check permissions — run the command as the same user that owns the socket or adjust socket ownership
- Increase -timeout if the daemon is slow to answer (e.g. -timeout 120)
- Check daemon logs for crashes and verify the daemon was started with the same config
Example fix
// before (config.yml) // (no socket section) // after (config.yml) socket: enabled: true
Defensive patterns
Strategy: retry
Validate before calling
if [ ! -S /var/run/litestream.sock ]; then echo "control socket missing: enable socket.enabled in config and start the daemon"; exit 1; fi
Try / catch
err := registerCmd.Run(ctx, args)
if err != nil && strings.Contains(err.Error(), "failed to connect to control socket") {
// backoff and retry a bounded number of times
time.Sleep(2 * time.Second)
err = registerCmd.Run(ctx, args)
} Prevention
- Enable `socket.enabled: true` in the daemon config and restart before registering
- Check the socket file exists with ls -l before invoking
- Run the CLI as the user that owns the socket
- Use a generous -timeout (30s default is fine)
When it happens
Trigger: Running `litestream register` while the litestream server is not running; the IPC socket is disabled (default: socket.enabled not set to true); wrong -socket path; timeout too small; permissions on the socket file block connecting.
Common situations: User forgot to enable `socket.enabled: true` in the litestream config and restart the daemon; daemon crashed or was restarted; running as a different user than the socket owner; SELinux/AppArmor blocking /var/run/litestream.sock.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- failed to connect to control socket: %w
- failed to read response: %w
- failed to connect to control socket: %w
- failed to read response: %w
- register failed: %s
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/ae30326c02591668.
Report an issue: GitHub.