FiloSottile/age · error

labels %q do not match previous recipients %q

Error message

labels %q do not match previous recipients %q

What it means

checkLabels verifies that all recipients produced by this plugin declare the same stanza label set as previously generated recipients for the same file key. age requires every stanza for a file key to carry consistent labels, so a plugin returning recipients with differing labels fails the whole wrap operation.

Source

Thrown at plugin/plugin.go:367

	}

	if err := writeStanza(p.stdout, "done"); err != nil {
		return p.fatalf("failed to write done stanza: %v", err)
	}
	return 0
}

func wrapWithLabels(r age.Recipient, fileKey []byte) ([]*age.Stanza, []string, error) {
	if r, ok := r.(age.RecipientWithLabels); ok {
		return r.WrapWithLabels(fileKey)
	}
	s, err := r.Wrap(fileKey)
	return s, nil, err
}

func checkLabels(ll, labels []string) error {
	if !slices.Equal(ll, labels) {
		return fmt.Errorf("labels %q do not match previous recipients %q", ll, labels)
	}
	return nil
}

// IdentityV1 implements the identity-v1 state machine. It returns an exit code
// to pass to os.Exit.
//
// Most plugins should call [Plugin.Main] instead of this method.
func (p *Plugin) IdentityV1() int {
	if p.identity == nil {
		return p.fatalf("identity-v1 not supported")
	}

	var files [][]*age.Stanza
	var identityStrings []string

	p.sr = format.NewStanzaReader(bufio.NewReader(p.stdin))
ReadLoop:

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. Make the plugin's Recipient return a fixed, deterministic label set for every recipient instance
  2. Remove conditional label logic so all recipients from the plugin declare identical labels
  3. Align the labels with the plugin spec's required label list for that plugin type

Example fix

// before
func (r *plugRecipient) Labels() []string {
    if r.legacy { return []string{"postprompt"} }
    return nil
}
// after
func (r *plugRecipient) Labels() []string { return []string{"postprompt"} }
Defensive patterns

Strategy: validation

Validate before calling

// In the plugin, unit-test label consistency across recipients:
labels := r1.Labels()
for _, r := range []Recipient{r1, r2, r3} {
    if !slices.Equal(r.Labels(), labels) {
        t.Fatalf("inconsistent labels: %v vs %v", r.Labels(), labels)
    }
}

Prevention

When it happens

Trigger: The plugin's Recipient.Wrap returns stanzas whose Labels() differ between multiple recipients for one file key; a recipient nondeterministically returns different label sets (e.g. conditional labels based on state or randomness).

Common situations: A custom plugin whose Wrap emits an extra label (e.g. "postprompt") for some recipients but not others; mixing an old and new recipient type inside one plugin.

Related errors


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