larksuite/cli · warning

busdiscover: malformed timestamp in %s: %w

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.

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)

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.