larksuite/cli · warning

busdiscover: malformed timestamp in

Error message

busdiscover: malformed timestamp in %s: %w

What it means

readPIDFile wraps strconv/time parse failures when reading a bus pidfile. The first line must be an integer PID and the second line an RFC3339 timestamp; if either fails to parse, the pidfile is considered corrupt and the error reports the file path plus the underlying parse cause via %w.

Solutions

  1. Delete the corrupt pidfile (or the whole stale bus directory under eventsDir) so scanLiveBuses skips it and a fresh bus can rewrite it
  2. Check the pidfile content: line 1 must be an integer PID, line 2 must be RFC3339 (e.g. 2026-09-04T10:00:00Z); fix or regenerate it
  3. Ensure no concurrent writers truncate the file while the bus starts; verify the process that writes the pidfile completes atomically (write-then-rename)
  4. Confirm clock/timezone tooling used to generate the timestamp emits RFC3339 with Z or offset

Example fix

// before (corrupt pidfile)
12345
2026-09-04 10:00:00
// after (valid pidfile)
12345
2026-09-04T10:00:00Z
Defensive patterns

Strategy: validation

Validate before calling

func validPIDFile(path string) bool {
	b, err := os.ReadFile(path)
	if err != nil || len(b) == 0 {
		return false
	}
	lines := strings.Split(strings.TrimSpace(string(b)), "\n")
	if len(lines) < 2 {
		return false
	}
	if _, err := strconv.Atoi(strings.TrimSpace(lines[0])); err != nil {
		return false
	}
	_, err = time.Parse(time.RFC3339, strings.TrimSpace(lines[1]))
	return err == nil
}

Prevention

When it happens

Trigger: scanLiveBuses encounters a pidfile whose line 1 is not a decimal integer (raises 'malformed pid') or whose line 2 is not a valid time.RFC3339 timestamp (raises 'malformed timestamp').

Common situations: A bus process crashed mid-write leaving a truncated pidfile; a user or script hand-edited the pidfile; the file contains a timestamp with wrong format (e.g. unix epoch number or local time string instead of RFC3339 like '2026-09-04T12:00:00Z'); an empty or whitespace-only second line after a partial write.

Understand the failure class

Related errors


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

Appendix: source

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

}

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
	}
	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

View on GitHub (pinned to 7fd6ef3c07)