larksuite/cli · error

pnpm install timed out after

Error message

pnpm install timed out after %s

What it means

RunPnpmInstall runs `pnpm add -g @larksuite/cli@<version>` under a context bounded by npmInstallTimeout. When the command exceeds the deadline, the context is canceled and this error replaces the underlying exec error to explain the timeout.

Solutions

  1. Check connectivity and pnpm registry configuration (`pnpm config get registry`), then retry the update
  2. Warm or clean the pnpm store (`pnpm store prune`) and retry
  3. Use a faster registry mirror via `pnpm config set registry <mirror>`
  4. Install manually outside the timeout: `pnpm add -g @larksuite/cli@latest`

Example fix

// before
res := updater.RunPnpmInstall("1.2.3")
if res.Err != nil { log.Fatal(res.Err) }
// after
res := updater.RunPnpmInstall("1.2.3")
if res.Err != nil {
	if strings.Contains(res.Err.Error(), "timed out") {
		// do the install outside the CLI's bounded timeout
		err := exec.Command("pnpm", "add", "-g", "@larksuite/cli@latest").Run()
		if err != nil { log.Fatal(err) }
	} else {
		log.Fatal(res.Err)
	}
}
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := exec.LookPath("pnpm"); err != nil { return }
out, err := exec.Command("pnpm", "config", "get", "registry").Output() // confirm a reachable registry

Try / catch

res := updater.RunPnpmInstall(version)
if res.Err != nil {
	if strings.Contains(res.Err.Error(), "timed out after") {
		// handle timeout: manual `pnpm add -g` fallback
	} else {
		return res.Err
	}
}

Prevention

When it happens

Trigger: Calling Updater.RunPnpmInstall(version) during a self-update when the spawned `pnpm add -g` process runs longer than npmInstallTimeout, i.e. ctx.Err() == context.DeadlineExceeded after cmd.Run().

Common situations: Slow network to the npm registry through pnpm's configured store/mirror; cold pnpm store requiring full download; low-resources VM or CI runner; proxy latency; very large install graph triggered by global store misses.

Understand the failure class

Related errors


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

Appendix: source

Thrown at internal/selfupdate/updater.go:276

// RunPnpmInstall executes pnpm add -g @larksuite/cli@<version>.
func (u *Updater) RunPnpmInstall(version string) *NpmResult {
	if u.PnpmInstallOverride != nil {
		return u.PnpmInstallOverride(version)
	}
	r := &NpmResult{}
	pnpmPath, err := exec.LookPath("pnpm")
	if err != nil {
		r.Err = fmt.Errorf("pnpm not found in PATH: %w", err)
		return r
	}
	ctx, cancel := context.WithTimeout(context.Background(), npmInstallTimeout)
	defer cancel()
	cmd := exec.CommandContext(ctx, pnpmPath, "add", "-g", NpmPackage+"@"+version)
	cmd.Stdout = &r.Stdout
	cmd.Stderr = &r.Stderr
	r.Err = cmd.Run()
	if ctx.Err() == context.DeadlineExceeded {
		r.Err = fmt.Errorf("pnpm install timed out after %s", npmInstallTimeout)
	}
	return r
}

func (u *Updater) FetchSkillsIndex(source string) *NpmResult {
	if u.SkillsIndexFetchOverride != nil {
		return u.SkillsIndexFetchOverride()
	}

	r := &NpmResult{}
	ctx, cancel := context.WithTimeout(context.Background(), skillsIndexFetchTimeout)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, skillsIndexURL(source), nil)
	if err != nil {
		r.Err = err
		return r
	}

View on GitHub (pinned to 7fd6ef3c07)