larksuite/cli · error

busdiscover: read events dir: %w

Error message

busdiscover: read events dir: %w

What it means

scanLiveBuses wraps any error from vfs.ReadDir on the events directory (other than NotExist, which is treated as zero buses). This means the directory exists but could not be read — permission denial, I/O error, or path-not-a-directory.

Source

Thrown at internal/event/adapter/localbus/busdiscover/pidfile.go:108

	err := probe.TryLock()
	if errors.Is(err, lockfile.ErrHeld) {
		return true
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "[busdiscover] probe %s: %v\n", lockPath, err) //nolint:forbidigo // internal diagnostic; scanner has no IOStreams plumbing
		return false
	}
	_ = probe.Unlock()
	return false
}

func scanLiveBuses(eventsDir string) ([]Process, error) {
	entries, err := vfs.ReadDir(eventsDir)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("busdiscover: read events dir: %w", err)
	}
	var result []Process
	for _, e := range entries {
		if !e.IsDir() {
			continue
		}
		appID := e.Name()
		appDir := filepath.Join(eventsDir, appID)
		if !isBusAlive(appDir) {
			continue
		}
		pid, startTime, err := readPIDFile(appDir)
		if err != nil {
			fmt.Fprintf(os.Stderr, "[busdiscover] live bus at %s but pid file unreadable: %v\n", appDir, err) //nolint:forbidigo // internal diagnostic; scanner has no IOStreams plumbing
			result = append(result, Process{PID: 0, AppID: appID})
			continue
		}
		result = append(result, Process{PID: pid, AppID: appID, StartTime: startTime})

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Check permissions: the scanning process needs read+execute on the events directory (ls -ld <eventsDir>; chown/chmod as needed)
  2. Verify the path is actually a directory (file eventsDir); if it is a file, remove it so it can be recreated as a directory
  3. Check filesystem health/mount status (dmesg, mount output) if I/O errors appear
  4. Ensure the app dir/state dir env pointing at the events dir is correct and not overridden to an unusable path

Example fix

// before: events path is a regular file
$ file ~/.lark/events  -> ~/.lark/events: ASCII text
$ rm ~/.lark/events   # let the CLI recreate it as a directory
// after: directory with sane perms
$ mkdir -p ~/.lark/events && chmod 755 ~/.lark/events
Defensive patterns

Strategy: try-catch

Validate before calling

info, err := os.Stat(eventsDir)
if err != nil || !info.IsDir() {
	// path missing or not a directory — fix permissions or recreate before scanning
}
// also check readability: f, err := os.Open(eventsDir); f.Close()

Try / catch

procs, err := busdiscover.ScanBusProcesses(appDir)
var pe *fs.PathError
if err != nil {
	if errors.As(err, &pe) && pe.Op == "open" {
		// permission/path problem: report eventsDir, suggest chown/chmod
	} else {
		return fmt.Errorf("scan failed: %w", err)
	}
}

Prevention

When it happens

Trigger: Calling ScanBusProcesses (or the tests) when eventsDir exists but ReadDir fails with a non-ENOENT error: e.g. the path is a regular file instead of a directory, or the process lacks read permission on it.

Common situations: LARKSUITE_CLI config/state dir owned by another user or restrictive umask; events path accidentally created as a file by a buggy earlier version; read-only or corrupted filesystem; container volume mounted with wrong permissions.

Related errors


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