FiloSottile/age · error

malformed recipient stanza: unexpected index

Error message

malformed recipient stanza: unexpected index

What it means

The plugin sent a recipient-stanza with a valid numeric index, but the index is not 0. The client sends only a single file key to the plugin, so any stanza claiming to wrap a different file key index is invalid and rejected.

Source

Thrown at plugin/client.go:125

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
			}
		case "labels":
			if labels != nil {
				return nil, nil, fmt.Errorf("repeated labels stanza")
			}
			labels = s.Args

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

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. Upgrade or fix the plugin so every returned recipient-stanza uses index 0.
  2. Clear any plugin-side caching that could carry stanza indices between wrap sessions.
  3. Capture the offending stanza and file a bug with the plugin maintainer.
  4. Retry with a fresh plugin process to rule out stale state.

Example fix

// before (plugin side)
n := lastUsedIndex // stale state, e.g. 1
writeStanza(conn, "recipient-stanza", strconv.Itoa(n), stanzaType)
// after
writeStanza(conn, "recipient-stanza", "0", stanzaType) // only one file key is sent
Defensive patterns

Strategy: validation

Validate before calling

// Go: assert index 0 before accepting a stanza when only one file key is sent
n, err := strconv.Atoi(args[0])
if err == nil && n != 0 {
    return fmt.Errorf("plugin returned stanza for unexpected file key index %d", n)
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "unexpected index") {
        return fmt.Errorf("plugin state bug (non-zero stanza index); restart plugin process or upgrade: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: WrapWithLabels/Wrap receives a recipient-stanza whose parsed index n is nonzero, meaning the plugin claims to wrap a file key other than the one sent, indicating a protocol/state bug in the plugin.

Common situations: A plugin that echoes cached stanzas from a previous session; a plugin that enumerates multiple file keys incorrectly; a buggy third-party plugin reusing stanza code across sessions.

Understand the failure class

Related errors


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