Skip to content

Plugin load/compile errors are effectively silent #395

Description

@eugenioenko

Summary

When a plugin fails to load, the failure is effectively invisible to the user. The error is captured and logged, but never surfaced in a way anyone would notice — so a broken plugin looks indistinguishable from a plugin that loaded and simply isn't responding.

Surfaced while building the Vim compatibility layer (#386), where a genuine compile failure cost significant debugging time precisely because nothing told us the plugin hadn't loaded.

Current behavior

Plugin.Init() captures a load error into p.LastError and logs it to slog (internal/plugin/plugin.go:28-32), then returns. But:

  • No notification is shown at startup when a plugin fails to load.
  • The only user-facing signal is the "Installed Plugins" dialog, which renders the status as the bare word error (internal/app/commands_plugin.go:109) — the actual message never reaches the user.
  • Because key.press listener errors are also swallowed at dispatch (internal/plugin/plugin.go, DispatchKeyEvent), a plugin that loaded but throws mid-handler is also silent, and looks identical to "didn't load."

Net effect: a broken plugin presents as "my keys do nothing" with no breadcrumb pointing at the plugin, let alone the reason.

Why it matters

Real failure modes that are currently silent:

  • gopher-lua's 200-live-locals-per-scope limit (Lua 5.1). Verified: a scope with 201 locals fails to compile with too many local variables. A large plugin's main chunk hits this; the workaround is do ... end blocks, but nothing tells the author that's the problem.
  • Any syntax error, nil call, or bad require at load time.
  • Any error thrown inside a key.press (or other event) listener at runtime.

Every one of these currently reads as "the plugin silently doesn't work."

Proposed changes

  1. Surface load failures at startup — a notification such as Plugin 'vim' failed to load — see Installed Plugins when Init() returns an error during Manager.LoadAll.
  2. Show the actual message in the Installed Plugins dialog — display p.LastError text (or a truncated form) next to the error status, not just the word error.
  3. Consider surfacing swallowed listener errors — e.g. rate-limited notification, or at least a visible indicator, the first time an event listener throws, so a runtime error in a handler isn't indistinguishable from a no-op.

Also worth documenting (docs, cheaper)

The gopher-lua constraints that make silent failure so likely are not written down for plugin authors. Add to plugin-authoring.md:

  • gopher-lua is Lua 5.1: no %g, no goto, no //, no utf8 library.
  • 200 live locals per scope; use do ... end blocks to release registers in large plugins.
  • Multi-file plugins are not supported (the sandbox strips package.loaders).
  • gopher-lua codegen bug: multiple assignment is not simultaneous for local variables — local a,b = b,a yields b,b (table-field targets are fine). Use an explicit temporary.

The doc portion will land alongside #386's plugin-authoring updates; this issue tracks the not-silent behavior change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions