benbjohnson/litestream · error

info failed: %s

Error message

info failed: %s

What it means

When the /info endpoint returns a non-200 status, Run attempts to decode the body as a litestream.ErrorResponse and, if it carries a non-empty Error field, surfaces it as `info failed: <server error>`. This is the server's structured error message passed through to the CLI user.

Source

Thrown at cmd/litestream/info.go:62

			},
		},
	}

	resp, err := client.Get("http://localhost/info")
	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("info failed: %s", errResp.Error)
		}
		return fmt.Errorf("info failed: %s", string(body))
	}

	var result litestream.InfoResponse
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("failed to parse response: %w", err)
	}

	if *jsonOutput {
		output, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return fmt.Errorf("failed to format response: %w", err)
		}
		fmt.Println(string(output))
	} else {
		uptime := time.Duration(result.UptimeSeconds) * time.Second
		fmt.Printf("Litestream %s\n", result.Version)

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Read the embedded <server error> text — it states the actual daemon-side reason — and address it.
  2. Check litestream daemon logs at the matching timestamp for the full error and stack.
  3. Ensure client and daemon versions match (upgrade/downgrade the CLI to the daemon's version).
  4. If the daemon is unhealthy (500s), restart the litestream process.

Example fix

// before (diagnose from message)
$ litestream info
info failed: store not initialized
// after
$ systemctl restart litestream
$ litestream info
Litestream v0.5.0 ...
Defensive patterns

Strategy: try-catch

Try / catch

out, err := runInfo(ctx)
if err != nil && strings.HasPrefix(err.Error(), "info failed: ") {
    serverMsg := strings.TrimPrefix(err.Error(), "info failed: ")
    log.Errorf("daemon rejected /info: %s — check daemon logs and version match", serverMsg)
    return
}

Prevention

When it happens

Trigger: The daemon handles the request but rejects it, responding with a JSON error body such as {"error":"..."} and an HTTP error status (e.g. internal error while collecting info, IPC not fully initialized).

Common situations: Daemon under load or mid-shutdown returning 500s; a version mismatch where the client's /info request is rejected by the running daemon; the socket is enabled but the server-side info handler fails to enumerate databases.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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