FiloSottile/age · warning
client failed to display message
Error message
client failed to display message
What it means
DisplayMessage is used by the plugin to show a message to the user via the age client's display-message protocol command. This error means the client answered the ok-or-fail exchange with a "fail" stanza — the client could not or refused to display the message. The plugin surfaces it as a normal error rather than a fatal interaction failure.
Source
Thrown at plugin/plugin.go:512
return 0
}
// DisplayMessage requests that the client display a message to the user. The
// message should start with a lowercase letter and have no final period.
// DisplayMessage returns an error if the client can't display the message, and
// may return before the message has been displayed to the user.
//
// It must only be called by a Wrap or Unwrap method invoked by [Plugin.Main].
func (p *Plugin) DisplayMessage(message string) error {
if err := writeStanzaWithBody(p.stdout, "msg", []byte(message)); err != nil {
return p.fatalInteractf("failed to write msg stanza: %v", err)
}
s, err := readOkOrFail(p.sr)
if err != nil {
return p.fatalInteractf("%v", err)
}
if s.Type == "fail" {
return fmt.Errorf("client failed to display message")
}
if err := expectStanzaWithNoBody(s, 0); err != nil {
return p.fatalInteractf("%v", err)
}
return nil
}
// RequestValue requests a secret or public input from the user through the
// client, with the provided prompt. It returns an error if the client can't
// request the input or if the user dismisses the prompt.
//
// It must only be called by a Wrap or Unwrap method invoked by [Plugin.Main].
func (p *Plugin) RequestValue(prompt string, secret bool) (string, error) {
t := "request-public"
if secret {
t = "request-secret"
}
if err := writeStanzaWithBody(p.stdout, t, []byte(prompt)); err != nil {View on GitHub (pinned to b74dce4cdb)
Solutions
- Treat the display as best-effort and continue without it, or surface the message through stderr instead
- Run age in an environment where the client can display messages
- Upgrade the age client to a version supporting the display-message plugin command
Example fix
// before
if err := p.DisplayMessage("confirm device presence"); err != nil { return err }
// after
if err := p.DisplayMessage("confirm device presence"); err != nil {
fmt.Fprintf(os.Stderr, "note: %s\n", "confirm device presence") // continue
} Defensive patterns
Strategy: try-catch
Validate before calling
// Prefer running age interactively; check TTY before non-interactive flows: // stat, _ := os.Stdin.Stat(); interactive := stat.Mode()&os.ModeCharDevice != 0
Try / catch
if err := p.DisplayMessage(msg); err != nil {
// non-fatal: log to stderr and continue
fmt.Fprintf(os.Stderr, "display skipped: %v\n", err)
} Prevention
- Treat DisplayMessage as best-effort, not a required step
- Avoid headless environments for plugins needing user messages
- Check client age version supports plugin UI commands
When it happens
Trigger: The age client running the plugin does not support display-message or its UI has no way to show messages (e.g. headless/batch mode); the client explicitly fails the request.
Common situations: Running age in a non-interactive environment (CI, scripts) where the client cannot show GUI/dialog messages; an old age client version lacking the display-message command; a client UI that drops the message.
Related errors
- client failed to request value
- client failed to request confirmation
- %s plugin: %w
- couldn't start plugin: %w
- malformed recipient stanza: unexpected argument count
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/52714df9cbf35849.
Report an issue: GitHub.