FiloSottile/age · error

malformed recipient stanza: unexpected argument count

Error message

malformed recipient stanza: unexpected argument count

What it means

The client received a 'recipient-stanza' from the plugin whose Args slice has fewer than 2 elements. The recipient-v1 protocol requires Args[0] to be the file-key index and Args[1] to be the stanza type, so a short stanza is treated as a protocol violation by the plugin.

Source

Thrown at plugin/client.go:117

		return nil, nil, err
	}
	if err := writeStanza(conn, "done"); err != nil {
		return nil, nil, err
	}

	// Phase 2: plugin responds with stanzas
	sr := format.NewStanzaReader(bufio.NewReader(conn))
ReadLoop:
	for {
		s, err := r.ui.readStanza(r.name, sr)
		if err != nil {
			return nil, nil, err
		}

		switch s.Type {
		case "recipient-stanza":
			if len(s.Args) < 2 {
				return nil, nil, fmt.Errorf("malformed recipient stanza: unexpected argument count")
			}
			n, err := strconv.Atoi(s.Args[0])
			if err != nil {
				return nil, nil, fmt.Errorf("malformed recipient stanza: invalid index")
			}
			// We only send a single file key, so the index must be 0.
			if n != 0 {
				return nil, nil, fmt.Errorf("malformed recipient stanza: unexpected index")
			}

			stanzas = append(stanzas, &age.Stanza{
				Type: s.Args[1],
				Args: s.Args[2:],
				Body: s.Body,
			})

			if err := writeStanza(conn, "ok"); err != nil {
				return nil, nil, err

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. Upgrade the plugin to the latest version so it emits recipient stanzas as '<index> <type> [args...]'.
  2. If you develop the plugin, fix the writer to send at least two args (index then stanza type).
  3. Capture the raw stanza with debug logging to confirm which side is malformed.
  4. Report the bug to the plugin maintainer if it is third-party code.

Example fix

// before (plugin side, buggy)
writeStanza(conn, "recipient-stanza", stanzaType) // missing index
// after
writeStanza(conn, "recipient-stanza", "0", stanzaType, extraArgs...)
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate recipient-stanza args before processing if you implement a plugin client
type Stanza struct{ Type string; Args []string; Body []byte }
func validRecipientStanza(s Stanza) bool {
    return s.Type == "recipient-stanza" && len(s.Args) >= 2
}

Type guard

func isRecipientStanzaWithArgs(s Stanza) bool {
    return s.Type == "recipient-stanza" && len(s.Args) >= 2
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "malformed recipient stanza") {
        return fmt.Errorf("plugin not conformant with recipient-v1; upgrade the plugin: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling WrapWithLabels/Wrap against a plugin that emits a recipient-stanza with missing arguments, i.e. a buggy, outdated, or non-conformant plugin speaking the recipient-v1 protocol incorrectly.

Common situations: Running an old plugin version that predates the index-argument convention; a hand-written third-party plugin with a protocol bug; garbled plugin response due to IO issues; testing a plugin under development that writes malformed stanzas.

Understand the failure class

Related errors


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