FiloSottile/age · error

failed to read response stanza: %v

Error message

failed to read response stanza: %v

What it means

readOkOrFail reads the next stanza for interactive commands (DisplayMessage, RequestValue, Confirm) and wraps any ReadStanza failure with this message. The client needs either 'ok' or 'fail' to continue but the stream broke first — typically the plugin died mid-dialog or emitted unparseable framing.

Source

Thrown at plugin/plugin.go:643

	}
	return 3
}

func expectOk(sr *format.StanzaReader) error {
	ok, err := sr.ReadStanza()
	if err != nil {
		return fmt.Errorf("failed to read OK stanza: %v", err)
	}
	if ok.Type != "ok" {
		return fmt.Errorf("expected OK stanza, got %q", ok.Type)
	}
	return expectStanzaWithNoBody(ok, 0)
}

func readOkOrFail(sr *format.StanzaReader) (*format.Stanza, error) {
	s, err := sr.ReadStanza()
	if err != nil {
		return nil, fmt.Errorf("failed to read response stanza: %v", err)
	}
	switch s.Type {
	case "fail":
		if err := expectStanzaWithNoBody(s, 0); err != nil {
			return nil, fmt.Errorf("%v", err)
		}
		return s, nil
	case "ok":
		return s, nil
	default:
		return nil, fmt.Errorf("expected ok or fail stanza, got %q", s.Type)
	}
}

func expectUnsupported(sr *format.StanzaReader) error {
	unsupported, err := sr.ReadStanza()
	if err != nil {
		return fmt.Errorf("failed to read unsupported stanza: %v", err)

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. Inspect the plugin's stderr for a crash or abort message at the time of the dialog
  2. Re-run the operation to see if the failure is reproducible or a transient pipe issue
  3. Verify the plugin writes complete stanzas (data lines plus terminating blank line)
  4. Update the plugin to the latest version and retest

Example fix

// before (plugin side)
fmt.Printf("-> ok") // no terminating blank line

// after
fmt.Printf("-> ok\n\n")
Defensive patterns

Strategy: try-catch

Try / catch

s, err := readOkOrFail(sr)
if err != nil {
    if strings.Contains(err.Error(), "failed to read response stanza") {
        return fmt.Errorf("plugin %s ended mid-dialog: %w", pluginName, err)
    }
    return err
}

Prevention

When it happens

Trigger: During a Confirm or RequestValue exchange the plugin's stdout yields an I/O error or unexpected EOF instead of a well-formed stanza; missing blank-line terminator on the plugin's reply.

Common situations: Plugin crashes while prompting the user; user aborts and the plugin kills its own output pipe; long-running prompt exceeds a timeout and the pipe is reaped; plugin writes a stanza without its empty-line terminator.

Related errors


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