larksuite/cli · warning

busdiscover: malformed pid in %s: %w

Error message

busdiscover: malformed pid in %s: %w

What it means

readPIDFile throws this when the first line of bus.pid is present but strconv.Atoi cannot parse it as an integer PID. Like the malformed-file case, scanLiveBuses logs it and reports the live bus with PID 0 instead of failing the scan. A wrapped strconv.NumError is preserved via %w.

Source

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

		_ = lock.Unlock()
		return nil, fmt.Errorf("busdiscover: rename pid file: %w", err)
	}
	return &Handle{lock: lock}, nil
}

func readPIDFile(eventsDir string) (int, time.Time, error) {
	pidPath := filepath.Join(eventsDir, pidFileName)
	data, err := vfs.ReadFile(pidPath)
	if err != nil {
		return 0, time.Time{}, err
	}
	lines := strings.SplitN(strings.TrimSpace(string(data)), "\n", 2)
	if len(lines) < 2 {
		return 0, time.Time{}, fmt.Errorf("busdiscover: malformed pid file %s", pidPath)
	}
	pid, err := strconv.Atoi(strings.TrimSpace(lines[0]))
	if err != nil {
		return 0, time.Time{}, fmt.Errorf("busdiscover: malformed pid in %s: %w", pidPath, err)
	}
	startTime, err := time.Parse(time.RFC3339, strings.TrimSpace(lines[1]))
	if err != nil {
		return 0, time.Time{}, fmt.Errorf("busdiscover: malformed timestamp in %s: %w", pidPath, err)
	}
	return pid, startTime, nil
}

// isBusAlive: try-lock the alive file. ErrHeld = live holder; success = stale (release immediately).
func isBusAlive(appDir string) bool {
	lockPath := filepath.Join(appDir, aliveLockFileName)
	if _, err := vfs.Stat(lockPath); err != nil {
		return false
	}
	probe := lockfile.New(lockPath)
	err := probe.TryLock()
	if errors.Is(err, lockfile.ErrHeld) {
		return true

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the corrupt bus.pid and restart the bus so WritePIDFile writes a clean '<pid>\n<timestamp>' payload
  2. Verify the first line is digits only (inspect with od -c or cat -A for BOM/CRLF) and strip any editor artifacts
  3. Identify and stop whatever external tool is writing a non-standard format into bus.pid
  4. If the bus is dead, delete the whole stale app directory so discovery stops reporting PID 0

Example fix

// before: pid line not an integer
$ cat bus.pid
PID: 1234
2026-09-04T08:00:00Z
// after: republish correct payload
$ rm bus.pid && restart the bus
$ cat bus.pid
1234
2026-09-04T08:00:00Z
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the pid line parses before relying on scan output
func pidLineIsNumeric(path string) bool {
    data, err := os.ReadFile(path)
    if err != nil { return false }
    first := strings.SplitN(strings.TrimSpace(string(data)), "\n", 2)[0]
    _, err = strconv.Atoi(strings.TrimSpace(first))
    return err == nil
}

Type guard

// Narrow scan results to entries with a parseable PID
func withValidPID(ps []busdiscover.Process) []busdiscover.Process {
    out := make([]busdiscover.Process, 0, len(ps))
    for _, p := range ps {
        if p.PID > 0 { out = append(out, p) }
    }
    return out
}

Try / catch

procs, _ := scanLiveBuses(eventsDir)
for _, p := range procs {
    if p.PID == 0 {
        log.Warnf("bus for %s holds alive lock but pid file is unparseable; skipping signal", p.AppID)
        continue
    }
    signal(p.PID)
}

Prevention

When it happens

Trigger: bus.pid's first line is non-numeric — e.g. the file was overwritten with arbitrary text, contains a BOM or CRLF artifacts combined with stray characters, or a tool wrote a different format into the pid slot.

Common situations: Manual edits pasting text into bus.pid, another program hijacking the well-known filename, copy-pasted content with whitespace/labels like 'PID: 1234', or encoding issues (UTF-8 BOM) from editors.

Understand the failure class

Related errors


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