FiloSottile/age · error
client failed to request value
Error message
client failed to request value
What it means
RequestValue asks the age client to prompt the user for a secret value via the request-value protocol command. This error means the client replied with a "fail" stanza — it could not obtain the requested value. The plugin gets an error instead of a value string.
Source
Thrown at plugin/plugin.go:538
// 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 {
return "", p.fatalInteractf("failed to write 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 request value")
}
if err := expectStanzaWithAnyBody(s, 0); err != nil {
return "", p.fatalInteractf("%v", err)
}
return string(s.Body), nil
}
// Confirm requests a confirmation from the user through the client, with the
// provided prompt. The yes and no value are the choices provided to the user.
// no may be empty. The return value choseYes indicates whether the user
// selected the yes or no option. Confirm returns an error if the client can't
// request the confirmation.
//
// It must only be called by a Wrap or Unwrap method invoked by [Plugin.Main].
func (p *Plugin) Confirm(prompt, yes, no string) (choseYes bool, err error) {
args := []string{format.EncodeToString([]byte(yes))}
if no != "" {
args = append(args, format.EncodeToString([]byte(no)))View on GitHub (pinned to b74dce4cdb)
Solutions
- Provide the value out of band (e.g. rely on the client's own -i/passphrase mechanisms) or degrade gracefully when the request fails
- Run age interactively so the client can prompt the user
- Upgrade the age client to a version implementing request-value
Example fix
// before
pin, err := p.RequestValue(false, "PIN")
if err != nil { return err }
// after
pin, err := p.RequestValue(false, "PIN")
if err != nil {
if env := os.Getenv("PLUGIN_PIN"); env != "" { pin = env } else { return err }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure an interactive prompt source exists before requesting:
// if os.Getenv("CI") != "" { skip RequestValue and use env/config instead } Try / catch
val, err := p.RequestValue(false, "PIN")
if err != nil {
if strings.Contains(err.Error(), "client failed to request value") {
// fall back to env var or fail with clear guidance
}
return err
} Prevention
- Provide out-of-band secret sources (env vars, config) for CI
- Request values only when interaction is possible
- Test plugins in non-interactive mode
When it happens
Trigger: The client cannot prompt (non-interactive session, no TTY, GUI unavailable); the client rejects the message or request for some reason; the user cancels in a way the client maps to fail.
Common situations: PIN/passphrase request for a hardware token in a headless CI run; old age client without request-value support; automated scripts with no interactive input available.
Related errors
- client failed to display message
- 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/e7c824586400bdb7.
Report an issue: GitHub.