benbjohnson/litestream · error

failed to read response: %w

Error message

failed to read response: %w

What it means

After a successful POST to the control socket, the command reads the entire response body with io.ReadAll. If reading fails (connection reset mid-response, socket error, or the client -timeout firing while streaming the body), the error is wrapped as 'failed to read response'.

Source

Thrown at cmd/litestream/register.go:80

	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 {
		return fmt.Errorf("failed to parse response: %w", err)
	}

	confirmation := RegisterResult{
		Status:  result.Status,
		DBPath:  result.Path,

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Increase -timeout (e.g. -timeout 60 or higher)
  2. Retry the register command — registration is idempotent (returns already_registered)
  3. Check daemon logs around the time of the failure for crashes or handler panics
  4. Verify system resources (OOM killer, disk) if the daemon dies mid-response

Example fix

// before
litestream register -timeout 1 -replica s3://b/p /db
// after
litestream register -timeout 60 -replica s3://b/p /db
Defensive patterns

Strategy: retry

Try / catch

if err := registerCmd.Run(ctx, args); err != nil {
    if strings.Contains(err.Error(), "failed to read response") {
        time.Sleep(backoff)
        err = registerCmd.Run(ctx, args) // registration is idempotent
    }
}

Prevention

When it happens

Trigger: The daemon closes the connection before the full response is delivered; the -timeout expires while io.ReadAll is still draining the body; I/O error on the Unix socket.

Common situations: Very small -timeout values with a slow/blocked daemon handler; daemon killed mid-request (systemd restart, OOM kill); flaky socket conditions under heavy load.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/ac41d06304be4d18. Report an issue: GitHub.