FiloSottile/age · error

repeated labels stanza

Error message

repeated labels stanza

What it means

The plugin sent more than one 'labels' stanza during the wrap protocol. A plugin must emit at most one labels stanza describing its supported labels, so a second one is a protocol violation and the client aborts.

Source

Thrown at plugin/client.go:139

				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 {
				return nil, nil, err
			}
		case "error":
			if err := writeStanza(conn, "ok"); err != nil {
				return nil, nil, err
			}

			return nil, nil, fmt.Errorf("%s", s.Body)
		case "done":
			break ReadLoop
		default:
			if ok, err := r.ui.handle(r.name, conn, s); err != nil {
				return nil, nil, err
			} else if !ok {

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. If you develop the plugin, emit the labels stanza exactly once, outside any per-stanza loop.
  2. Upgrade the plugin to the latest version where the duplicate-labels bug is fixed.
  3. Capture the plugin transcript to confirm which code path sends labels twice.
  4. Report the bug to the plugin maintainer if it is not your code.

Example fix

// before (plugin side, buggy)
for _, st := range stanzas {
    writeStanza(conn, "recipient-stanza", "0", st.Type, st.Args...)
    writeStanza(conn, "labels", "post-quantum") // emitted each iteration
}
// after
for _, st := range stanzas {
    writeStanza(conn, "recipient-stanza", "0", st.Type, st.Args...)
}
writeStanza(conn, "labels", "post-quantum") // once
Defensive patterns

Strategy: validation

Validate before calling

// Go (plugin side): emit labels exactly once
type labelsWriter struct{ sent bool }
func (w *labelsWriter) writeLabels(conn io.Writer, labels ...string) error {
    if w.sent { return fmt.Errorf("labels already sent") }
    w.sent = true
    return writeStanza(conn, "labels", labels...)
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "repeated labels stanza") {
        return fmt.Errorf("plugin bug: duplicate labels stanza; upgrade plugin: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling WrapWithLabels/Wrap with a plugin that sends duplicate 'labels' stanzas in response to the file key, e.g. a buggy plugin loop that emits labels once per stanza instead of once per session.

Common situations: Developing a custom plugin and emitting labels inside a per-stanza loop; a plugin version bug where labels are re-sent after an 'ok'; misbehaving third-party plugins.

Related errors


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