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

  1. Provide the value out of band (e.g. rely on the client's own -i/passphrase mechanisms) or degrade gracefully when the request fails
  2. Run age interactively so the client can prompt the user
  3. 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

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


AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31). Data as JSON: /api/errors/e7c824586400bdb7. Report an issue: GitHub.