apache/answer · error
failed to install plugin dependencies: %w
Error message
failed to install plugin dependencies: %w
What it means
For each vendored plugin that has a package.json (i.e. a UI plugin), copyUIFiles runs `pnpm install` inside the plugin's source directory to install its frontend dependencies. This error wraps the exec.ExitError from a failing pnpm install — the plugin's JS dependencies could not be installed.
Source
Thrown at internal/cli/build.go:368
if err != nil {
return fmt.Errorf("failed to read plugins dir: %w", err)
}
for _, entry := range pluginsDirEntries {
if !entry.IsDir() {
continue
}
sourcePluginDir := filepath.Join(pluginsDir, entry.Name())
// check if plugin is a ui plugin
packageJsonPath := filepath.Join(sourcePluginDir, "package.json")
fmt.Printf("check if %s is a ui plugin\n", packageJsonPath)
if !dir.CheckFileExist(packageJsonPath) {
continue
}
pnpmInstallCmd := b.newExecCmd("pnpm", "install")
pnpmInstallCmd.Dir = sourcePluginDir
if err = pnpmInstallCmd.Run(); err != nil {
return fmt.Errorf("failed to install plugin dependencies: %w", err)
}
localPluginDir := filepath.Join(localUIPluginDir, entry.Name())
fmt.Printf("try to copy dir from %s to %s\n", sourcePluginDir, localPluginDir)
if err = copyDirEntries(os.DirFS(sourcePluginDir), ".", localPluginDir, "node_modules"); err != nil {
return fmt.Errorf("failed to copy ui files: %w", err)
}
}
formatUIPluginsDirName(localUIPluginDir)
return nil
}
// buildUI run pnpm install and pnpm build commands to build ui
func buildUI(b *buildingMaterial) (err error) {
localUIBuildDir := filepath.Join(b.tmpDir, "vendor/github.com/apache/answer/ui")
pnpmInstallCmd := b.newExecCmd("pnpm", "pre-install")
pnpmInstallCmd.Dir = localUIBuildDirView on GitHub (pinned to 3b9f137061)
Solutions
- Ensure pnpm is installed and on PATH (`pnpm -v`); install the version the answer build expects (e.g. `npm i -g pnpm` or corepack).
- Reproduce manually: `cd <plugin-dir> && pnpm install` and read the pnpm output to see the real failure (registry 404, peer conflict, Node version).
- Fix the plugin's package.json/pnpm-lock.yaml: update deps or run `pnpm install --no-frozen-lockfile`; for private/old packages check registry access.
- Check network/proxy config for pnpm (npm registry mirror, HTTPS_PROXY) and Node version compatibility, then rebuild.
Example fix
// before: pnpm failure surfaced with no context
pnpmInstallCmd := b.newExecCmd("pnpm", "install")
pnpmInstallCmd.Dir = sourcePluginDir
if err = pnpmInstallCmd.Run(); err != nil {
return fmt.Errorf("failed to install plugin dependencies: %w", err)
}
// after: verify pnpm availability and capture output
if _, err := exec.LookPath("pnpm"); err != nil {
return fmt.Errorf("pnpm is required to build UI plugins: %w", err)
}
pnpmInstallCmd := b.newExecCmd("pnpm", "install")
pnpmInstallCmd.Dir = sourcePluginDir
pnpmInstallCmd.Stdout = os.Stdout
pnpmInstallCmd.Stderr = os.Stderr
if err = pnpmInstallCmd.Run(); err != nil {
return fmt.Errorf("failed to install plugin dependencies in %s: %w", sourcePluginDir, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := exec.LookPath("pnpm"); err != nil {
return fmt.Errorf("pnpm not found in PATH; install it (npm i -g pnpm or corepack enable)")
}
pkgJson := filepath.Join(sourcePluginDir, "package.json")
if _, err := os.Stat(pkgJson); err != nil {
return fmt.Errorf("plugin %s has no package.json", sourcePluginDir)
}
// optional connectivity check
if err := probeRegistry("https://registry.npmjs.org"); err != nil {
return fmt.Errorf("npm registry unreachable; check proxy/network: %w", err)
} Type guard
func pnpmAvailable() bool {
p, err := exec.LookPath("pnpm")
return err == nil && p != ""
}
func isUIPlugin(pluginDir string) bool {
fi, err := os.Stat(filepath.Join(pluginDir, "package.json"))
return err == nil && !fi.IsDir()
} Try / catch
var exitErr *exec.ExitError
if err := pnpmInstallCmd.Run(); err != nil {
if errors.As(err, &exitErr) {
return fmt.Errorf("pnpm install failed in %s (exit %d); run 'cd %s && pnpm install' for details: %w",
sourcePluginDir, exitErr.ExitCode(), sourcePluginDir, err)
}
return fmt.Errorf("failed to start pnpm (is it installed?): %w", err)
} Prevention
- Install pnpm and a compatible Node version before running `answer build` (check .nvmrc / packageManager field).
- Pin plugin dependencies and commit pnpm-lock.yaml so installs are reproducible.
- Configure npm registry mirrors / HTTPS_PROXY for corporate or restricted networks.
- Test third-party plugins with a standalone `pnpm install` in the plugin dir before adding them to the build.
- Avoid pinning deps to versions that may be unpublished/removed from the registry.
When it happens
Trigger: b.newExecCmd("pnpm", "install").Run() with Dir=sourcePluginDir returns an error: pnpm binary not on PATH, the plugin's package.json/pnpm-lock.yaml is broken or references unpublished versions/registry packages, network failure reaching the npm registry, or pnpm exits non-zero (peer conflicts, unsupported Node version).
Common situations: Custom third-party plugin with an outdated lockfile or dependencies that no longer resolve; corporate proxy/firewall blocking registry.npmjs.org; pnpm not installed (answer build requires it) or wrong Node/pnpm version; plugin's package.json pinned to a removed package version.
Related errors
- failed to run go list: %w
- failed to read plugins dir: %w
- failed to clone %s@%s: %w Tip: set ANSWER_MODULE to a local
- failed to copy ui files: %w
- failed to create directory %s: %w
AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05).
Data as JSON: /api/errors/f17ee678742181c6.
Report an issue: GitHub.