larksuite/cli · error

bus probe: encode: %w

Error message

bus probe: encode: %w

What it means

During startup, probeAndDialBus opens a probe connection to the local event bus, sets a 2s deadline, and writes a StatusQuery frame via protocol.Encode. If encoding/writing the status query fails, the probe is closed and the error is wrapped as 'bus probe: encode: %w', causing EnsureBus to fail startup rather than proceed against an unhealthy bus. This is a local IPC failure, not a remote API error.

Source

Thrown at internal/event/consume/startup.go:107

	logPath := filepath.Join(core.GetConfigDir(), "events", event.SanitizeAppID(appID), "bus.log")
	fmt.Fprintln(errOut, "[event] event bus exited unexpectedly.")
	fmt.Fprintln(errOut, "[event] please check app credentials (lark-cli config show) and retry.")
	fmt.Fprintf(errOut, "[event] logs: %s\n", logPath)
	return nil, errs.NewInternalError(errs.SubtypeUnknown,
		"failed to connect to event bus within %v (app=%s)", dialTimeout, appID).
		WithHint("check app credentials (`lark-cli config show`) and retry; bus logs: %s", logPath)
}

// probeAndDialBus distinguishes a healthy bus from a mid-shutdown listener via StatusQuery first.
func probeAndDialBus(tr transport.IPC, addr string) (net.Conn, error) {
	probe, err := tr.Dial(addr)
	if err != nil {
		return nil, err
	}
	probe.SetDeadline(time.Now().Add(2 * time.Second))
	if err := protocol.Encode(probe, protocol.NewStatusQuery()); err != nil {
		probe.Close()
		return nil, fmt.Errorf("bus probe: encode: %w", err)
	}
	br := bufio.NewReader(probe)
	line, err := protocol.ReadFrame(br)
	probe.Close()
	if err != nil {
		return nil, fmt.Errorf("bus probe: read status: %w", err)
	}
	msg, err := protocol.Decode(bytes.TrimRight(line, "\n"))
	if err != nil {
		return nil, fmt.Errorf("bus probe: decode status: %w", err)
	}
	if _, ok := msg.(*protocol.StatusResponse); !ok {
		return nil, fmt.Errorf("bus probe: expected StatusResponse, got %T", msg)
	}

	return tr.Dial(addr)
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the stale bus socket/lock file and restart the CLI so a fresh bus is spawned.
  2. Check whether the bus process is running and inspect its logs for crashes at probe time.
  3. Retry the command once — transient write-deadline misses self-heal when the bus recovers.
  4. If it persists, investigate protocol.Encode and the bus's read loop for version mismatch between writer and bus frame formats.
Defensive patterns

Strategy: retry

Validate before calling

// Verify the bus socket is alive before starting the full consumer
conn, err := net.DialTimeout("unix", busSocketPath, 2*time.Second)
if err != nil {
	// bus not listening: clean stale socket and let EnsureBus respawn it
} else {
	conn.Close()
}

Try / catch

cli, err := consume.EnsureBus(ctx, cfg)
if err != nil {
	if strings.Contains(err.Error(), "bus probe: encode") || strings.Contains(err.Error(), "bus probe: read status") {
		// transient/unhealthy bus: remove stale socket and retry once
		os.Remove(busSocketPath) //nolint: local CLI-owned state
		cli, err = consume.EnsureBus(ctx, cfg)
	}
	if err != nil { return fmt.Errorf("bus startup failed: %w", err) }
}

Prevention

When it happens

Trigger: protocol.Encode(probe, protocol.NewStatusQuery()) returns an error during EnsureBus: broken pipe because the bus process died or closed the socket, connection reset, write deadline (2s) exceeded on a busy/unresponsive bus, or bus socket in a bad state.

Common situations: Stale bus socket left over from a previous crashed run, bus process killed between connect and probe write, resource exhaustion making the local bus unresponsive, concurrent startup races where multiple consumers probe at once.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/091fc9dff5da3481. Report an issue: GitHub.