From 042d819c78c41aef5670f154a219e1b60dd7d46e Mon Sep 17 00:00:00 2001
From: David Hartunian <davidh@cockroachlabs.com>
Date: Tue, 1 Aug 2023 09:57:14 -0400
Subject: [PATCH 1/2] add formatting for multi-cause errors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Previously, error formatting logic was based on a single linear chain
of causality. Error causes would be printed vertically down the page,
and their interpretation was natural.

This commit adds multi-cause formatting support with two goals in
mind:
1. Preserve output exactly as before for single-cause error chains
2. Format multi-errors in a way that preserves the existing vertical
layout style.

For non-verbose error display (`.Error()`, `%s`, `%v`) there are no
changes implemented here. We rely on the error's own display logic and
typically a multi-cause error will have a message within that has been
constructed from all of its causes during instantiation.

For verbose error display (`%+v`) which relies on object
introspection, whenever we encounter a multi-cause error in the chain,
we mark that subtree as being displayed with markers for the "depth"
of various causes. All child errors of the parent, will be at depth
"1", their child errors will be at depth "2", etc. During display, we
indent the error by its "depth" and add a `└─` symbol to illustrate
the parent/child relationship.

Example:

Printing the error produced by this construction using the format directive `%+v`
```
fmt.Errorf(
	"prefix1: %w",
	fmt.Errorf(
		"prefix2 %w",
		goErr.Join(
			fmt.Errorf("a%w", fmt.Errorf("b%w", fmt.Errorf("c%w", goErr.New("d")))),
			fmt.Errorf("e%w", fmt.Errorf("f%w", fmt.Errorf("g%w", goErr.New("h")))),
)))
```

Produces the following output:

```
prefix1: prefix2: abcd
(1) prefix1
Wraps: (2) prefix2
Wraps: (3) abcd
  | efgh
  └─ Wraps: (4) efgh
    └─ Wraps: (5) fgh
      └─ Wraps: (6) gh
        └─ Wraps: (7) h
  └─ Wraps: (8) abcd
    └─ Wraps: (9) bcd
      └─ Wraps: (10) cd
        └─ Wraps: (11) d
Error types: (1) *fmt.wrapError (2) *fmt.wrapError (3)
*errors.joinError (4) *fmt.wrapError (5) *fmt.wrapError (6)
*fmt.wrapError (7) *errors.errorString (8) *fmt.wrapError (9)
*fmt.wrapError (10) *fmt.wrapError (11) *errors.errorString`,
```

Note the following properties of the output:
* The top-level single cause chain maintains the left-aligned `Wrap`
lines which contain each cause one at a time.
* As soon as we hit the multi-cause errors within the `joinError`
struct (`(3)`), we add new indentation to show that The child errors
of `(3)` are `(4)` and `(8)`
* Subsequent causes of errors after `joinError`, are also indented to
disambiguate the causal chain
* The `Error types` section at the bottom remains the same and the
numbering of the types can be matched to the errors above using the
integers next to the `Wrap` lines.
* No special effort has been made to number the errors in a way that
describes the causal chain or tree. This keeps it easy to match up the
error to its type descriptor.
---
 errbase/format_error.go                       | 124 ++++++--
 errbase/format_error_internal_test.go         | 281 ++++++++++++++++++
 fmttests/testdata/format/wrap-fmt             |  96 +++++-
 fmttests/testdata/format/wrap-fmt-via-network | 111 ++++++-
 fmttests/testdata/format/wrap-goerr           |  87 +++++-
 .../testdata/format/wrap-goerr-via-network    | 102 ++++++-
 fmttests/testdata/format/wrap-newf            | 165 +++++++++-
 .../testdata/format/wrap-newf-via-network     | 189 +++++++++++-
 fmttests/testdata/format/wrap-nofmt           |  87 +++++-
 .../testdata/format/wrap-nofmt-via-network    | 111 ++++++-
 fmttests/testdata/format/wrap-pkgerr          | 159 +++++++++-
 .../testdata/format/wrap-pkgerr-via-network   | 189 +++++++++++-
 report/report.go                              |  20 +-
 13 files changed, 1658 insertions(+), 63 deletions(-)

diff --git a/errbase/format_error.go b/errbase/format_error.go
index c6d50c8..406a513 100644
--- a/errbase/format_error.go
+++ b/errbase/format_error.go
@@ -102,7 +102,13 @@ func formatErrorInternal(err error, s fmt.State, verb rune, redactableOutput boo
 		// to enable stack trace de-duplication. This requires a
 		// post-order traversal. Since we have a linked list, the best we
 		// can do is a recursion.
-		p.formatRecursive(err, true /* isOutermost */, true /* withDetail */)
+		p.formatRecursive(
+			err,
+			true,  /* isOutermost */
+			true,  /* withDetail */
+			false, /* withDepth */
+			0,     /* depth */
+		)
 
 		// We now have all the data, we can render the result.
 		p.formatEntries(err)
@@ -146,7 +152,13 @@ func formatErrorInternal(err error, s fmt.State, verb rune, redactableOutput boo
 		// by calling FormatError(), in which case we'd get an infinite
 		// recursion. So we have no choice but to peel the data
 		// and then assemble the pieces ourselves.
-		p.formatRecursive(err, true /* isOutermost */, false /* withDetail */)
+		p.formatRecursive(
+			err,
+			true,  /* isOutermost */
+			false, /* withDetail */
+			false, /* withDepth */
+			0,     /* depth */
+		)
 		p.formatSingleLineOutput()
 		p.finishDisplay(verb)
 
@@ -195,7 +207,19 @@ func (s *state) formatEntries(err error) {
 	// Wraps: (N) <details>
 	//
 	for i, j := len(s.entries)-2, 2; i >= 0; i, j = i-1, j+1 {
-		fmt.Fprintf(&s.finalBuf, "\nWraps: (%d)", j)
+		s.finalBuf.WriteByte('\n')
+		// Extra indentation starts at depth==2 because the direct
+		// children of the root error area already printed on separate
+		// newlines.
+		for m := 0; m < s.entries[i].depth-1; m += 1 {
+			if m == s.entries[i].depth-2 {
+				s.finalBuf.WriteString("└─ ")
+			} else {
+				s.finalBuf.WriteByte(' ')
+				s.finalBuf.WriteByte(' ')
+			}
+		}
+		fmt.Fprintf(&s.finalBuf, "Wraps: (%d)", j)
 		entry := s.entries[i]
 		s.printEntry(entry)
 	}
@@ -330,12 +354,34 @@ func (s *state) formatSingleLineOutput() {
 // s.finalBuf is untouched. The conversion of s.entries
 // to s.finalBuf is done by formatSingleLineOutput() and/or
 // formatEntries().
-func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
+//
+// `withDepth` and `depth` are used to tag subtrees of multi-cause
+// errors for added indentation during printing. Once a multi-cause
+// error is encountered, all subsequent calls with set `withDepth` to
+// true, and increment `depth` during recursion. This information is
+// persisted into the generated entries and used later to display the
+// error with increased indentation based in the depth.
+func (s *state) formatRecursive(err error, isOutermost, withDetail, withDepth bool, depth int) int {
 	cause := UnwrapOnce(err)
+	numChildren := 0
 	if cause != nil {
-		// Recurse first.
-		s.formatRecursive(cause, false /*isOutermost*/, withDetail)
+		// Recurse first, which populates entries list starting from innermost
+		// entry. If we've previously seen a multi-cause wrapper, `withDepth`
+		// will be true, and we'll record the depth below ensuring that extra
+		// indentation is applied to this inner cause during printing.
+		// Otherwise, we maintain "straight" vertical formatting by keeping the
+		// parent callers `withDepth` value of `false` by default.
+		numChildren += s.formatRecursive(cause, false, withDetail, withDepth, depth+1)
+	}
+
+	causes := UnwrapMulti(err)
+	for _, c := range causes {
+		// Override `withDepth` to true for all child entries ensuring they have
+		// indentation applied during formatting to distinguish them from
+		// parents.
+		numChildren += s.formatRecursive(c, false, withDetail, true, depth+1)
 	}
+	// inserted := len(s.entries) - 1 - startChildren
 
 	// Reinitialize the state for this stage of wrapping.
 	s.wantDetail = withDetail
@@ -355,9 +401,11 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
 		bufIsRedactable = true
 		desiredShortening := v.SafeFormatError((*safePrinter)(s))
 		if desiredShortening == nil {
-			// The error wants to elide the short messages from inner
-			// causes. Do it.
-			s.elideFurtherCauseMsgs()
+			// The error wants to elide the short messages from inner causes.
+			// Read backwards through list of entries up to the number of new
+			// entries created "under" this one amount and mark `elideShort`
+			// true.
+			s.elideShortChildren(numChildren)
 		}
 
 	case Formatter:
@@ -365,7 +413,7 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
 		if desiredShortening == nil {
 			// The error wants to elide the short messages from inner
 			// causes. Do it.
-			s.elideFurtherCauseMsgs()
+			s.elideShortChildren(numChildren)
 		}
 
 	case fmt.Formatter:
@@ -389,7 +437,7 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
 			if elideCauseMsg := s.formatSimple(err, cause); elideCauseMsg {
 				// The error wants to elide the short messages from inner
 				// causes. Do it.
-				s.elideFurtherCauseMsgs()
+				s.elideShortChildren(numChildren)
 			}
 		}
 
@@ -412,7 +460,7 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
 				if desiredShortening == nil {
 					// The error wants to elide the short messages from inner
 					// causes. Do it.
-					s.elideFurtherCauseMsgs()
+					s.elideShortChildren(numChildren)
 				}
 				break
 			}
@@ -421,16 +469,21 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
 			// If the error did not implement errors.Formatter nor
 			// fmt.Formatter, but it is a wrapper, still attempt best effort:
 			// print what we can at this level.
-			if elideCauseMsg := s.formatSimple(err, cause); elideCauseMsg {
+			elideChildren := s.formatSimple(err, cause)
+			// always elideChildren when dealing with multi-cause errors.
+			if len(causes) > 0 {
+				elideChildren = true
+			}
+			if elideChildren {
 				// The error wants to elide the short messages from inner
 				// causes. Do it.
-				s.elideFurtherCauseMsgs()
+				s.elideShortChildren(numChildren)
 			}
 		}
 	}
 
 	// Collect the result.
-	entry := s.collectEntry(err, bufIsRedactable)
+	entry := s.collectEntry(err, bufIsRedactable, withDepth, depth)
 
 	// If there's an embedded stack trace, also collect it.
 	// This will get either a stack from pkg/errors, or ours.
@@ -444,21 +497,19 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
 	// Remember the entry for later rendering.
 	s.entries = append(s.entries, entry)
 	s.buf = bytes.Buffer{}
+
+	return numChildren + 1
 }
 
-// elideFurtherCauseMsgs sets the `elideShort` field
-// on all entries added so far to `true`. Because these
-// entries are added recursively from the innermost
-// cause outward, we can iterate through all entries
-// without bound because the caller is guaranteed not
-// to see entries that it is the causer of.
-func (s *state) elideFurtherCauseMsgs() {
-	for i := range s.entries {
-		s.entries[i].elideShort = true
+// elideShortChildren takes a number of entries to set `elideShort` to
+// false. The reason a number of entries is needed is because
+func (s *state) elideShortChildren(newEntries int) {
+	for i := 0; i < newEntries; i++ {
+		s.entries[len(s.entries)-1-i].elideShort = true
 	}
 }
 
-func (s *state) collectEntry(err error, bufIsRedactable bool) formatEntry {
+func (s *state) collectEntry(err error, bufIsRedactable bool, withDepth bool, depth int) formatEntry {
 	entry := formatEntry{err: err}
 	if s.wantDetail {
 		// The buffer has been populated as a result of formatting with
@@ -495,6 +546,10 @@ func (s *state) collectEntry(err error, bufIsRedactable bool) formatEntry {
 		}
 	}
 
+	if withDepth {
+		entry.depth = depth
+	}
+
 	return entry
 }
 
@@ -712,6 +767,11 @@ type formatEntry struct {
 	// truncated to avoid duplication of entries. This is used to
 	// display a truncation indicator during verbose rendering.
 	elidedStackTrace bool
+
+	// depth, if positive, represents a nesting depth of this error as
+	// a causer of others. This is used with verbose printing to
+	// illustrate the nesting depth for multi-cause error wrappers.
+	depth int
 }
 
 // String is used for debugging only.
@@ -733,6 +793,12 @@ func (s *state) Write(b []byte) (n int, err error) {
 
 	for i, c := range b {
 		if c == '\n' {
+			//if s.needNewline > 0 {
+			//	for i := 0; i < s.needNewline-1; i++ {
+			//		s.buf.Write(detailSep[:len(sep)-1])
+			//	}
+			//	s.needNewline = 0
+			//}
 			// Flush all the bytes seen so far.
 			s.buf.Write(b[k:i])
 			// Don't print the newline itself; instead, prepare the state so
@@ -762,6 +828,11 @@ func (s *state) Write(b []byte) (n int, err error) {
 			s.notEmpty = true
 		}
 	}
+	//if s.needNewline > 0 {
+	//	for i := 0; i < s.needNewline-1; i++ {
+	//		s.buf.Write(detailSep[:len(sep)-1])
+	//	}
+	//}
 	s.buf.Write(b[k:])
 	return len(b), nil
 }
@@ -788,6 +859,9 @@ func (p *state) switchOver() {
 	p.buf = bytes.Buffer{}
 	p.notEmpty = false
 	p.hasDetail = true
+
+	// One of the newlines is accounted for in the switch over.
+	// p.needNewline -= 1
 }
 
 func (s *printer) Detail() bool {
diff --git a/errbase/format_error_internal_test.go b/errbase/format_error_internal_test.go
index 0e4f93e..be00290 100644
--- a/errbase/format_error_internal_test.go
+++ b/errbase/format_error_internal_test.go
@@ -15,11 +15,292 @@
 package errbase
 
 import (
+	goErr "errors"
+	"fmt"
+	"strings"
 	"testing"
 
 	"github.com/cockroachdb/redact"
 )
 
+type wrapMini struct {
+	msg   string
+	cause error
+}
+
+func (e *wrapMini) Error() string {
+	return e.msg
+}
+
+func (e *wrapMini) Unwrap() error {
+	return e.cause
+}
+
+type wrapElideCauses struct {
+	override string
+	causes   []error
+}
+
+func NewWrapElideCauses(override string, errors ...error) error {
+	return &wrapElideCauses{
+		override: override,
+		causes:   errors,
+	}
+}
+
+func (e *wrapElideCauses) Unwrap() []error {
+	return e.causes
+}
+
+func (e *wrapElideCauses) SafeFormatError(p Printer) (next error) {
+	p.Print(e.override)
+	// Returning nil elides errors from remaining causal chain in the
+	// implementation of `formatErrorInternal`.
+	return nil
+}
+
+var _ SafeFormatter = &wrapElideCauses{}
+
+func (e *wrapElideCauses) Error() string {
+	b := strings.Builder{}
+	b.WriteString(e.override)
+	b.WriteString(": ")
+	for i, ee := range e.causes {
+		b.WriteString(ee.Error())
+		if i < len(e.causes)-1 {
+			b.WriteByte(' ')
+		}
+	}
+	return b.String()
+}
+
+type wrapNoElideCauses struct {
+	prefix string
+	causes []error
+}
+
+func NewWrapNoElideCauses(prefix string, errors ...error) error {
+	return &wrapNoElideCauses{
+		prefix: prefix,
+		causes: errors,
+	}
+}
+
+func (e *wrapNoElideCauses) Unwrap() []error {
+	return e.causes
+}
+
+func (e *wrapNoElideCauses) SafeFormatError(p Printer) (next error) {
+	p.Print(e.prefix)
+	return e.causes[0]
+}
+
+var _ SafeFormatter = &wrapNoElideCauses{}
+
+func (e *wrapNoElideCauses) Error() string {
+	b := strings.Builder{}
+	b.WriteString(e.prefix)
+	b.WriteString(": ")
+	for i, ee := range e.causes {
+		b.WriteString(ee.Error())
+		if i < len(e.causes)-1 {
+			b.WriteByte(' ')
+		}
+	}
+	return b.String()
+}
+
+// TestFormatErrorInternal attempts to highlight some idiosyncrasies of
+// the error formatting especially when used with multi-cause error
+// structures. Comments on specific cases below outline some gaps that
+// still require formatting tweaks.
+func TestFormatErrorInternal(t *testing.T) {
+	tests := []struct {
+		name            string
+		err             error
+		expectedSimple  string
+		expectedVerbose string
+	}{
+		{
+			name:           "single wrapper",
+			err:            fmt.Errorf("%w", fmt.Errorf("a%w", goErr.New("b"))),
+			expectedSimple: "ab",
+			expectedVerbose: `ab
+(1)
+Wraps: (2) ab
+Wraps: (3) b
+Error types: (1) *fmt.wrapError (2) *fmt.wrapError (3) *errors.errorString`,
+		},
+		{
+			name:           "simple multi-wrapper",
+			err:            goErr.Join(goErr.New("a"), goErr.New("b")),
+			expectedSimple: "a\nb",
+			// TODO(davidh): verbose test case should have line break
+			// between `a` and `b` on second line.
+			expectedVerbose: `a
+(1) ab
+Wraps: (2) b
+Wraps: (3) a
+Error types: (1) *errors.joinError (2) *errors.errorString (3) *errors.errorString`,
+		},
+		{
+			name: "multi-wrapper with custom formatter and partial elide",
+			err: NewWrapNoElideCauses("A",
+				NewWrapNoElideCauses("C", goErr.New("3"), goErr.New("4")),
+				NewWrapElideCauses("B", goErr.New("1"), goErr.New("2")),
+			),
+			expectedSimple: `A: B: C: 4: 3`, // 1 and 2 omitted because they are elided.
+			expectedVerbose: `A: B: C: 4: 3
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) 2
+└─ Wraps: (4) 1
+Wraps: (5) C
+└─ Wraps: (6) 4
+└─ Wraps: (7) 3
+Error types: (1) *errbase.wrapNoElideCauses (2) *errbase.wrapElideCauses (3) *errors.errorString (4) *errors.errorString (5) *errbase.wrapNoElideCauses (6) *errors.errorString (7) *errors.errorString`,
+		},
+		{
+			name: "multi-wrapper with custom formatter and no elide",
+			// All errors in this example omit eliding their children.
+			err: NewWrapNoElideCauses("A",
+				NewWrapNoElideCauses("B", goErr.New("1"), goErr.New("2")),
+				NewWrapNoElideCauses("C", goErr.New("3"), goErr.New("4")),
+			),
+			expectedSimple: `A: C: 4: 3: B: 2: 1`,
+			expectedVerbose: `A: C: 4: 3: B: 2: 1
+(1) A
+Wraps: (2) C
+└─ Wraps: (3) 4
+└─ Wraps: (4) 3
+Wraps: (5) B
+└─ Wraps: (6) 2
+└─ Wraps: (7) 1
+Error types: (1) *errbase.wrapNoElideCauses (2) *errbase.wrapNoElideCauses (3) *errors.errorString (4) *errors.errorString (5) *errbase.wrapNoElideCauses (6) *errors.errorString (7) *errors.errorString`,
+		},
+		{
+			name:           "simple multi-line error",
+			err:            goErr.New("a\nb\nc\nd"),
+			expectedSimple: "a\nb\nc\nd",
+			// TODO(davidh): verbose test case should preserve all 3
+			// linebreaks in original error.
+			expectedVerbose: `a
+(1) ab
+  |
+  | c
+  | d
+Error types: (1) *errors.errorString`,
+		},
+		{
+			name: "two-level multi-wrapper",
+			err: goErr.Join(
+				goErr.Join(goErr.New("a"), goErr.New("b")),
+				goErr.Join(goErr.New("c"), goErr.New("d")),
+			),
+			expectedSimple: "a\nb\nc\nd",
+			// TODO(davidh): verbose output should preserve line breaks after (1)
+			// and also after (2) and (5) in `c\nd` and `a\nb`.
+			expectedVerbose: `a
+(1) ab
+  |
+  | c
+  | d
+Wraps: (2) cd
+└─ Wraps: (3) d
+└─ Wraps: (4) c
+Wraps: (5) ab
+└─ Wraps: (6) b
+└─ Wraps: (7) a
+Error types: (1) *errors.joinError (2) *errors.joinError (3) *errors.errorString (4) *errors.errorString (5) *errors.joinError (6) *errors.errorString (7) *errors.errorString`,
+		},
+		{
+			name: "simple multi-wrapper with single-cause chains inside",
+			err: goErr.Join(
+				fmt.Errorf("a%w", goErr.New("b")),
+				fmt.Errorf("c%w", goErr.New("d")),
+			),
+			expectedSimple: "ab\ncd",
+			expectedVerbose: `ab
+(1) ab
+  | cd
+Wraps: (2) cd
+└─ Wraps: (3) d
+Wraps: (4) ab
+└─ Wraps: (5) b
+Error types: (1) *errors.joinError (2) *fmt.wrapError (3) *errors.errorString (4) *fmt.wrapError (5) *errors.errorString`,
+		},
+		{
+			name: "multi-cause wrapper with single-cause chains inside",
+			err: goErr.Join(
+				fmt.Errorf("a%w", fmt.Errorf("b%w", fmt.Errorf("c%w", goErr.New("d")))),
+				fmt.Errorf("e%w", fmt.Errorf("f%w", fmt.Errorf("g%w", goErr.New("h")))),
+			),
+			expectedSimple: `abcd
+efgh`,
+			expectedVerbose: `abcd
+(1) abcd
+  | efgh
+Wraps: (2) efgh
+└─ Wraps: (3) fgh
+  └─ Wraps: (4) gh
+    └─ Wraps: (5) h
+Wraps: (6) abcd
+└─ Wraps: (7) bcd
+  └─ Wraps: (8) cd
+    └─ Wraps: (9) d
+Error types: (1) *errors.joinError (2) *fmt.wrapError (3) *fmt.wrapError (4) *fmt.wrapError (5) *errors.errorString (6) *fmt.wrapError (7) *fmt.wrapError (8) *fmt.wrapError (9) *errors.errorString`},
+		{
+			name: "single cause chain with multi-cause wrapper inside with single-cause chains inside",
+			err: fmt.Errorf(
+				"prefix1: %w",
+				fmt.Errorf(
+					"prefix2: %w",
+					goErr.Join(
+						fmt.Errorf("a%w", fmt.Errorf("b%w", fmt.Errorf("c%w", goErr.New("d")))),
+						fmt.Errorf("e%w", fmt.Errorf("f%w", fmt.Errorf("g%w", goErr.New("h")))),
+					))),
+			expectedSimple: `prefix1: prefix2: abcd
+efgh`,
+			expectedVerbose: `prefix1: prefix2: abcd
+(1) prefix1
+Wraps: (2) prefix2
+Wraps: (3) abcd
+  | efgh
+  └─ Wraps: (4) efgh
+    └─ Wraps: (5) fgh
+      └─ Wraps: (6) gh
+        └─ Wraps: (7) h
+  └─ Wraps: (8) abcd
+    └─ Wraps: (9) bcd
+      └─ Wraps: (10) cd
+        └─ Wraps: (11) d
+Error types: (1) *fmt.wrapError (2) *fmt.wrapError (3) *errors.joinError (4) *fmt.wrapError (5) *fmt.wrapError (6) *fmt.wrapError (7) *errors.errorString (8) *fmt.wrapError (9) *fmt.wrapError (10) *fmt.wrapError (11) *errors.errorString`,
+		},
+		{
+			name:           "test wrapMini elides cause error string",
+			err:            &wrapMini{"whoa: d", goErr.New("d")},
+			expectedSimple: "whoa: d",
+			expectedVerbose: `whoa: d
+(1) whoa
+Wraps: (2) d
+Error types: (1) *errbase.wrapMini (2) *errors.errorString`,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			fe := Formattable(tt.err)
+			s := fmt.Sprintf("%s", fe)
+			if s != tt.expectedSimple {
+				t.Errorf("\nexpected: \n%s\nbut got:\n%s\n", tt.expectedSimple, s)
+			}
+			s = fmt.Sprintf("%+v", fe)
+			if s != tt.expectedVerbose {
+				t.Errorf("\nexpected: \n%s\nbut got:\n%s\n", tt.expectedVerbose, s)
+			}
+		})
+	}
+}
+
 func TestPrintEntry(t *testing.T) {
 	b := func(s string) []byte { return []byte(s) }
 
diff --git a/fmttests/testdata/format/wrap-fmt b/fmttests/testdata/format/wrap-fmt
index 91f1008..1911862 100644
--- a/fmttests/testdata/format/wrap-fmt
+++ b/fmttests/testdata/format/wrap-fmt
@@ -1658,7 +1658,37 @@ outerthree
 (1) outerthree
   | outerfour - innerone
   | innertwo sibling error in wrapper
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) sibling error in wrapper
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+  | -- this is innerone
+  | innertwo's
+  | multi-line leaf payload
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *fmttests.errFmt
 =====
 ===== redactable formats
 =====
@@ -1676,7 +1706,37 @@ Error types: (1) *fmt.wrapErrors
 (1) ‹outerthree›
 ‹  | outerfour - innerone›
 ‹  | innertwo sibling error in wrapper›
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ‹sibling error in wrapper›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func23›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Wraps: (3) ‹innerone›
+‹  | innertwo›
+‹  | -- this is innerone›
+‹  | innertwo's›
+‹  | multi-line leaf payload›
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *fmttests.errFmt
 =====
 ===== Sentry reporting
 =====
@@ -1685,7 +1745,37 @@ Error types: (1) *fmt.wrapErrors
 (1) ×
 ×
 ×
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Wraps: (3) ×
+×
+×
+×
+×
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *fmttests.errFmt
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-fmt-via-network b/fmttests/testdata/format/wrap-fmt-via-network
index c653d87..c152248 100644
--- a/fmttests/testdata/format/wrap-fmt-via-network
+++ b/fmttests/testdata/format/wrap-fmt-via-network
@@ -2165,7 +2165,42 @@ outerthree
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) sibling error in wrapper
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 == %#v via Formattable() = %#v, good
 == %v via Formattable() = Error(), good
 == %s via Formattable() = %v via Formattable(), good
@@ -2191,7 +2226,42 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ‹sibling error in wrapper›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 =====
 ===== Sentry reporting
 =====
@@ -2203,7 +2273,42 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-goerr b/fmttests/testdata/format/wrap-goerr
index e3594ef..fd97e94 100644
--- a/fmttests/testdata/format/wrap-goerr
+++ b/fmttests/testdata/format/wrap-goerr
@@ -1513,7 +1513,34 @@ outerthree
 (1) outerthree
   | outerfour - innerone
   | innertwo sibling error in wrapper
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) sibling error in wrapper
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *errors.errorString
 =====
 ===== redactable formats
 =====
@@ -1531,7 +1558,34 @@ Error types: (1) *fmt.wrapErrors
 (1) ‹outerthree›
 ‹  | outerfour - innerone›
 ‹  | innertwo sibling error in wrapper›
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ‹sibling error in wrapper›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func23›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Wraps: (3) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *errors.errorString
 =====
 ===== Sentry reporting
 =====
@@ -1540,7 +1594,34 @@ Error types: (1) *fmt.wrapErrors
 (1) ×
 ×
 ×
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Wraps: (3) ×
+×
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *errors.errorString
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-goerr-via-network b/fmttests/testdata/format/wrap-goerr-via-network
index 159524e..05a8e43 100644
--- a/fmttests/testdata/format/wrap-goerr-via-network
+++ b/fmttests/testdata/format/wrap-goerr-via-network
@@ -1774,7 +1774,39 @@ outerthree
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) sibling error in wrapper
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errors.errorString
 == %#v via Formattable() = %#v, good
 == %v via Formattable() = Error(), good
 == %s via Formattable() = %v via Formattable(), good
@@ -1800,7 +1832,39 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ‹sibling error in wrapper›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ‹innerone›
+‹  | innertwo›
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errors.errorString
 =====
 ===== Sentry reporting
 =====
@@ -1812,7 +1876,39 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ×
+×
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errors.errorString
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-newf b/fmttests/testdata/format/wrap-newf
index 6567b1c..823f653 100644
--- a/fmttests/testdata/format/wrap-newf
+++ b/fmttests/testdata/format/wrap-newf
@@ -3135,7 +3135,60 @@ outerthree
 (1) outerthree
   | outerfour - new-style innerone
   | innertwo sibling error in wrapper
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) sibling error in wrapper
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+└─ Wraps: (4) new-style innerone
+  | innertwo
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *withstack.withStack (4) *errutil.leafError
 =====
 ===== redactable formats
 =====
@@ -3153,7 +3206,60 @@ Error types: (1) *fmt.wrapErrors
 (1) ‹outerthree›
 ‹  | outerfour - new-style innerone›
 ‹  | innertwo sibling error in wrapper›
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ‹sibling error in wrapper›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func23›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+└─ Wraps: (4) new-style ‹innerone›
+  | ‹innertwo›
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *withstack.withStack (4) *errutil.leafError
 =====
 ===== Sentry reporting
 =====
@@ -3162,7 +3268,60 @@ Error types: (1) *fmt.wrapErrors
 (1) ×
 ×
 ×
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+└─ Wraps: (4) new-style ×
+  | ×
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *withstack.withStack (4) *errutil.leafError
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-newf-via-network b/fmttests/testdata/format/wrap-newf-via-network
index df5e711..57ebc9a 100644
--- a/fmttests/testdata/format/wrap-newf-via-network
+++ b/fmttests/testdata/format/wrap-newf-via-network
@@ -3699,7 +3699,68 @@ outerthree
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) sibling error in wrapper
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+└─ Wraps: (4) new-style innerone
+  | innertwo
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueWrapper (4) *errutil.leafError
 == %#v via Formattable() = %#v, good
 == %v via Formattable() = Error(), good
 == %s via Formattable() = %v via Formattable(), good
@@ -3725,7 +3786,68 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ‹sibling error in wrapper›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+└─ Wraps: (4) new-style ‹innerone›
+  | ‹innertwo›
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueWrapper (4) *errutil.leafError
 =====
 ===== Sentry reporting
 =====
@@ -3737,7 +3859,68 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+└─ Wraps: (4) new-style ×
+  | ×
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueWrapper (4) *errutil.leafError
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-nofmt b/fmttests/testdata/format/wrap-nofmt
index 666d4e9..c643809 100644
--- a/fmttests/testdata/format/wrap-nofmt
+++ b/fmttests/testdata/format/wrap-nofmt
@@ -1513,7 +1513,34 @@ outerthree
 (1) outerthree
   | outerfour - innerone
   | innertwo sibling error in wrapper
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) sibling error in wrapper
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *fmttests.errNoFmt
 =====
 ===== redactable formats
 =====
@@ -1531,7 +1558,34 @@ Error types: (1) *fmt.wrapErrors
 (1) ‹outerthree›
 ‹  | outerfour - innerone›
 ‹  | innertwo sibling error in wrapper›
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ‹sibling error in wrapper›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func23›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Wraps: (3) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *fmttests.errNoFmt
 =====
 ===== Sentry reporting
 =====
@@ -1540,7 +1594,34 @@ Error types: (1) *fmt.wrapErrors
 (1) ×
 ×
 ×
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Wraps: (3) ×
+×
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *fmttests.errNoFmt
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-nofmt-via-network b/fmttests/testdata/format/wrap-nofmt-via-network
index 71fc4b2..e9e84c5 100644
--- a/fmttests/testdata/format/wrap-nofmt-via-network
+++ b/fmttests/testdata/format/wrap-nofmt-via-network
@@ -2165,7 +2165,42 @@ outerthree
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) sibling error in wrapper
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 == %#v via Formattable() = %#v, good
 == %v via Formattable() = Error(), good
 == %s via Formattable() = %v via Formattable(), good
@@ -2191,7 +2226,42 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ‹sibling error in wrapper›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 =====
 ===== Sentry reporting
 =====
@@ -2203,7 +2273,42 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-pkgerr b/fmttests/testdata/format/wrap-pkgerr
index 3bfc433..3a351ff 100644
--- a/fmttests/testdata/format/wrap-pkgerr
+++ b/fmttests/testdata/format/wrap-pkgerr
@@ -3022,7 +3022,58 @@ outerthree
 (1) outerthree
   | outerfour - innerone
   | innertwo sibling error in wrapper
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) sibling error in wrapper
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *errors.fundamental
 =====
 ===== redactable formats
 =====
@@ -3040,7 +3091,58 @@ Error types: (1) *fmt.wrapErrors
 (1) ‹outerthree›
 ‹  | outerfour - innerone›
 ‹  | innertwo sibling error in wrapper›
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ‹sibling error in wrapper›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func23›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Wraps: (3) ‹innerone›
+‹  | innertwo›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func9›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *errors.fundamental
 =====
 ===== Sentry reporting
 =====
@@ -3049,7 +3151,58 @@ Error types: (1) *fmt.wrapErrors
 (1) ×
 ×
 ×
-Error types: (1) *fmt.wrapErrors
+Wraps: (2) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Wraps: (3) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Error types: (1) *fmt.wrapErrors (2) *errors.fundamental (3) *errors.fundamental
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/fmttests/testdata/format/wrap-pkgerr-via-network b/fmttests/testdata/format/wrap-pkgerr-via-network
index d9376e1..5a4cae3 100644
--- a/fmttests/testdata/format/wrap-pkgerr-via-network
+++ b/fmttests/testdata/format/wrap-pkgerr-via-network
@@ -3611,7 +3611,68 @@ outerthree
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) sibling error in wrapper
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 == %#v via Formattable() = %#v, good
 == %v via Formattable() = Error(), good
 == %s via Formattable() = %v via Formattable(), good
@@ -3637,7 +3698,68 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ‹sibling error in wrapper›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 =====
 ===== Sentry reporting
 =====
@@ -3649,7 +3771,68 @@ Error types: (1) *errbase.opaqueLeafCauses
   |
   | (opaque error leaf)
   | type name: fmt/*fmt.wrapErrors
-Error types: (1) *errbase.opaqueLeafCauses
+Wraps: (2) ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Wraps: (3) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *errbase.opaqueLeafCauses (2) *errbase.opaqueLeaf (3) *errbase.opaqueLeaf
 -- report composition:
 *fmt.wrapErrors
 == Extra "error types"
diff --git a/report/report.go b/report/report.go
index 0211722..cba95b0 100644
--- a/report/report.go
+++ b/report/report.go
@@ -34,7 +34,7 @@ import (
 //
 // A Sentry report is displayed visually in the Sentry UI as follows:
 //
-////////////////
+// //////////////
 // Title: (1) some prefix in bold (2) one line for a stack trace
 // (3) a single-line subtitle
 //
@@ -44,21 +44,24 @@ import (
 // (5) a "message"
 //
 // (6) zero or more "exceptions", each composed of:
-//    (7) a bold title
-//    (8) some freeform text
-//    (9) a stack trace
+//
+//	(7) a bold title
+//	(8) some freeform text
+//	(9) a stack trace
 //
 // (10) metadata fields: environment, arch, etc
 //
 // (11) "Additional data" fields
 //
 // (12) SDK version
-/////////////////
+// ///////////////
 //
 // These visual items map to the Sentry Event object as follows:
 //
 // (1) the Type field of the 1st Exception object, if any
-//     otherwise the Message field
+//
+//	otherwise the Message field
+//
 // (2) the topmost entry from the Stacktrace field of the 1st Exception object, if any
 // (3) the Value field of the 1st Exception object, if any, unwrapped as a single line
 // (4) the Tags field
@@ -78,7 +81,9 @@ import (
 // (3)/(8): first line of verbose error printout
 // (4): not populated in this function, caller is to manage this
 // (5): detailed structure of the entire error object, with references to
-//      additional "exception" objects
+//
+//	additional "exception" objects
+//
 // (9): generated from innermost stack trace
 // (6): every exception object after the 1st reports additional stack trace contexts
 // (11): the detailed error types and their error mark.
@@ -92,7 +97,6 @@ import (
 // is included in the Sentry report. This does not affect error types
 // provided by the library, but could impact error types defined by
 // 3rd parties. This limitation may be lifted in a later version.
-//
 func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string]interface{}) {
 	if err == nil {
 		// No error: do nothing.

From 6adb34fbb2ccc70bb80d9f529fbdd7a2cfa9234d Mon Sep 17 00:00:00 2001
From: David Hartunian <davidh@cockroachlabs.com>
Date: Mon, 21 Aug 2023 17:24:21 -0400
Subject: [PATCH 2/2] Implement custom encode/decode for multi-cause errors

Previous support for multi-cause encode/decode functionality, did not
include support for custom encoder and decoder logic.

This commits adds the ability to register encoders and decoders for
multi-cause errors to encode custom types unknown to this library.
---
 errbase/decode.go                             |   30 +
 errbase/encode.go                             |   22 +
 errbase/format_error.go                       |    5 +-
 errbase_api.go                                |   32 +-
 fmttests/datadriven_test.go                   |   14 +
 fmttests/format_error_test.go                 |   52 +
 fmttests/testdata/format/wrap-fmt             |  640 ++++++++++
 fmttests/testdata/format/wrap-fmt-via-network |  950 ++++++++++++++
 fmttests/testdata/format/wrap-goerr           |  622 +++++++++
 .../testdata/format/wrap-goerr-via-network    |  900 +++++++++++++
 fmttests/testdata/format/wrap-newf            |  778 ++++++++++++
 .../testdata/format/wrap-newf-via-network     | 1114 +++++++++++++++++
 fmttests/testdata/format/wrap-nofmt           |  622 +++++++++
 .../testdata/format/wrap-nofmt-via-network    |  950 ++++++++++++++
 fmttests/testdata/format/wrap-pkgerr          |  766 ++++++++++++
 .../testdata/format/wrap-pkgerr-via-network   | 1106 ++++++++++++++++
 16 files changed, 8601 insertions(+), 2 deletions(-)

diff --git a/errbase/decode.go b/errbase/decode.go
index 2de4a30..59af230 100644
--- a/errbase/decode.go
+++ b/errbase/decode.go
@@ -57,6 +57,15 @@ func decodeLeaf(ctx context.Context, enc *errorspb.EncodedErrorLeaf) error {
 			return genErr
 		}
 		// Decoding failed, we'll drop through to opaqueLeaf{} below.
+	} else if decoder, ok := multiCauseDecoders[typeKey]; ok {
+		causes := make([]error, len(enc.MultierrorCauses))
+		for i, e := range enc.MultierrorCauses {
+			causes[i] = DecodeError(ctx, *e)
+		}
+		genErr := decoder(ctx, causes, enc.Message, enc.Details.ReportablePayload, payload)
+		if genErr != nil {
+			return genErr
+		}
 	} else {
 		// Shortcut for non-registered proto-encodable error types:
 		// if it already implements `error`, it's good to go.
@@ -174,3 +183,24 @@ type WrapperDecoder = func(ctx context.Context, cause error, msgPrefix string, s
 
 // registry for RegisterWrapperType.
 var decoders = map[TypeKey]WrapperDecoder{}
+
+// MultiCauseDecoder is to be provided (via RegisterMultiCauseDecoder
+// above) by additional multi-cause wrapper types not yet known by the
+// library. A nil return indicates that decoding was not successful.
+type MultiCauseDecoder = func(ctx context.Context, causes []error, msgPrefix string, safeDetails []string, payload proto.Message) error
+
+// registry for RegisterMultiCauseDecoder.
+var multiCauseDecoders = map[TypeKey]MultiCauseDecoder{}
+
+// RegisterMultiCauseDecoder can be used to register new multi-cause
+// wrapper types to the library. Registered wrappers will be decoded
+// using their own Go type when an error is decoded. Multi-cause
+// wrappers that have not been registered will be decoded using the
+// opaqueWrapper type.
+func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder) {
+	if decoder == nil {
+		delete(multiCauseDecoders, theType)
+	} else {
+		multiCauseDecoders[theType] = decoder
+	}
+}
diff --git a/errbase/encode.go b/errbase/encode.go
index 80d4799..418cc50 100644
--- a/errbase/encode.go
+++ b/errbase/encode.go
@@ -328,6 +328,28 @@ type LeafEncoder = func(ctx context.Context, err error) (msg string, safeDetails
 // registry for RegisterLeafEncoder.
 var leafEncoders = map[TypeKey]LeafEncoder{}
 
+// RegisterMultiCauseEncoder can be used to register new multi-cause
+// error types to the library. Registered types will be encoded using
+// their own Go type when an error is encoded. Multi-cause wrappers
+// that have not been registered will be encoded using the
+// opaqueWrapper type.
+func RegisterMultiCauseEncoder(theType TypeKey, encoder MultiCauseEncoder) {
+	// This implementation is a simple wrapper around `LeafEncoder`
+	// because we implemented multi-cause error wrapper encoding into a
+	// `Leaf` instead of a `Wrapper` for smoother backwards
+	// compatibility support. Exposing this detail to consumers of the
+	// API is confusing and hence avoided. The causes of the error are
+	// encoded separately regardless of this encoder's implementation.
+	RegisterLeafEncoder(theType, encoder)
+}
+
+// MultiCauseEncoder is to be provided (via RegisterMultiCauseEncoder
+// above) by additional multi-cause wrapper types not yet known to this
+// library. The encoder will automatically extract and encode the
+// causes of this error by calling `Unwrap()` and expecting a slice of
+// errors.
+type MultiCauseEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message)
+
 // RegisterWrapperEncoder can be used to register new wrapper types to
 // the library. Registered wrappers will be encoded using their own
 // Go type when an error is encoded. Wrappers that have not been
diff --git a/errbase/format_error.go b/errbase/format_error.go
index 406a513..ada144b 100644
--- a/errbase/format_error.go
+++ b/errbase/format_error.go
@@ -502,7 +502,10 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail, withDepth bo
 }
 
 // elideShortChildren takes a number of entries to set `elideShort` to
-// false. The reason a number of entries is needed is because
+// false. The reason a number of entries is needed is that we may be
+// eliding a subtree of causes in the case of a multi-cause error. In
+// the multi-cause case, we need to know how many of the prior errors
+// in the list of entries is a child of this subtree.
 func (s *state) elideShortChildren(newEntries int) {
 	for i := 0; i < newEntries; i++ {
 		s.entries[len(s.entries)-1-i].elideShort = true
diff --git a/errbase_api.go b/errbase_api.go
index b33f896..da410f9 100644
--- a/errbase_api.go
+++ b/errbase_api.go
@@ -86,6 +86,20 @@ func GetTypeKey(err error) TypeKey { return errbase.GetTypeKey(err) }
 // A nil return indicates that decoding was not successful.
 type LeafDecoder = errbase.LeafDecoder
 
+// MultiCauseDecoder is to be provided (via RegisterMultiCauseDecoder
+// above) by additional multi-cause wrapper types not yet known by the
+// library. A nil return indicates that decoding was not successful.
+type MultiCauseDecoder = errbase.MultiCauseDecoder
+
+// RegisterMultiCauseDecoder can be used to register new multi-cause
+// wrapper types to the library. Registered wrappers will be decoded
+// using their own Go type when an error is decoded. Multi-cause
+// wrappers that have not been registered will be decoded using the
+// opaqueWrapper type.
+func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder) {
+	errbase.RegisterMultiCauseDecoder(theType, decoder)
+}
+
 // RegisterWrapperDecoder can be used to register new wrapper types to
 // the library. Registered wrappers will be decoded using their own
 // Go type when an error is decoded. Wrappers that have not been
@@ -145,7 +159,7 @@ type WrapperEncoder = errbase.WrapperEncoder
 // Note: if the error type has been migrated from a previous location
 // or a different type, ensure that RegisterTypeMigration() was called
 // prior to RegisterWrapperEncoder().
-func RegisterWrapperEncoderWithMessageType(typeName TypeKey, encoder errbase.WrapperEncoderWithMessageType) {
+func RegisterWrapperEncoderWithMessageType(typeName TypeKey, encoder WrapperEncoderWithMessageType) {
 	errbase.RegisterWrapperEncoderWithMessageType(typeName, encoder)
 }
 
@@ -154,6 +168,22 @@ func RegisterWrapperEncoderWithMessageType(typeName TypeKey, encoder errbase.Wra
 // types not yet known to this library.
 type WrapperEncoderWithMessageType = errbase.WrapperEncoderWithMessageType
 
+// RegisterMultiCauseEncoder can be used to register new multi-cause
+// error types to the library. Registered types will be encoded using
+// their own Go type when an error is encoded. Multi-cause wrappers
+// that have not been registered will be encoded using the
+// opaqueWrapper type.
+func RegisterMultiCauseEncoder(typeName TypeKey, encoder MultiCauseEncoder) {
+	errbase.RegisterMultiCauseEncoder(typeName, encoder)
+}
+
+// MultiCauseEncoder is to be provided (via RegisterMultiCauseEncoder
+// above) by additional multi-cause wrapper types not yet known to this
+// library. The encoder will automatically extract and encode the
+// causes of this error by calling `Unwrap()` and expecting a slice of
+// errors.
+type MultiCauseEncoder = errbase.MultiCauseEncoder
+
 // SetWarningFn enables configuration of the warning function.
 func SetWarningFn(fn func(context.Context, string, ...interface{})) { errbase.SetWarningFn(fn) }
 
diff --git a/fmttests/datadriven_test.go b/fmttests/datadriven_test.go
index 90aafd1..c1eb9fa 100644
--- a/fmttests/datadriven_test.go
+++ b/fmttests/datadriven_test.go
@@ -207,6 +207,20 @@ var wrapCommands = map[string]commandFn{
 	// werrWithElidedClause overrides its cause's Error() from its own
 	// short message.
 	"elided-cause": func(err error, args []arg) error { return &werrWithElidedCause{err, strfy(args)} },
+	"multi-cause": func(err error, args []arg) error {
+		return newMultiCause("A", false, /* elide */
+			newMultiCause("C", false /* elide */, err, errutil.New(strfy(args))),
+			newMultiCause("B", false /* elide */, errutil.New("included 1"), errutil.New("included 2")),
+		)
+	},
+	// This iteration elides the causes in the second child error,
+	// which omits them from the format string.
+	"multi-elided-cause": func(err error, args []arg) error {
+		return newMultiCause("A", false, /* elide */
+			newMultiCause("C", false /* elide */, err, errutil.New(strfy(args))),
+			newMultiCause("B", true /* elide */, errutil.New("elided 1"), errutil.New("elided 2")),
+		)
+	},
 
 	// stack attaches a simple stack trace.
 	"stack": func(err error, _ []arg) error { return withstack.WithStack(err) },
diff --git a/fmttests/format_error_test.go b/fmttests/format_error_test.go
index 44e5cdb..db8e1a3 100644
--- a/fmttests/format_error_test.go
+++ b/fmttests/format_error_test.go
@@ -733,3 +733,55 @@ func (w *werrSafeFormat) SafeFormatError(p errbase.Printer) (next error) {
 	p.Printf("safe %s", w.msg)
 	return w.cause
 }
+
+type errMultiCause struct {
+	causes []error
+	msg    string
+	elide  bool
+}
+
+func newMultiCause(msg string, elide bool, causes ...error) *errMultiCause {
+	return &errMultiCause{
+		causes: causes,
+		msg:    msg,
+		elide:  elide,
+	}
+}
+
+func (e *errMultiCause) Error() string                 { return fmt.Sprint(e) }
+func (e *errMultiCause) Format(s fmt.State, verb rune) { errbase.FormatError(e, s, verb) }
+func (e *errMultiCause) SafeFormatError(p errbase.Printer) (next error) {
+	p.Printf("%s", e.msg)
+	if e.elide {
+		return nil
+	} else {
+		return e.causes[0]
+	}
+}
+func (e *errMultiCause) Unwrap() []error { return e.causes }
+
+func init() {
+	errbase.RegisterMultiCauseEncoder(errbase.GetTypeKey(&errMultiCause{}), encodeWithMultiCause)
+	errbase.RegisterMultiCauseDecoder(errbase.GetTypeKey(&errMultiCause{}), decodeWithMultiCause)
+}
+
+func encodeWithMultiCause(
+	_ context.Context, err error,
+) (string, []string, proto.Message) {
+	m := err.(*errMultiCause)
+	if m.elide {
+		return m.msg, []string{"elide"}, nil
+	} else {
+		return m.msg, nil, nil
+	}
+}
+
+func decodeWithMultiCause(
+	_ context.Context, causes []error, msg string, details []string, _ proto.Message,
+) error {
+	elide := false
+	if len(details) == 1 && details[0] == "elide" {
+		elide = true
+	}
+	return &errMultiCause{causes, msg, elide}
+}
diff --git a/fmttests/testdata/format/wrap-fmt b/fmttests/testdata/format/wrap-fmt
index 1911862..1625ad0 100644
--- a/fmttests/testdata/format/wrap-fmt
+++ b/fmttests/testdata/format/wrap-fmt
@@ -2420,6 +2420,646 @@ Type: "*fmttests.errFmt"
 Title: "outerthree: ×"
 (NO STACKTRACE)
 
+run
+fmt innerone innertwo
+multi-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  | -- this is innerone
+  | innertwo's
+  | multi-line leaf payload
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errFmt
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+‹  | -- this is innerone›
+‹  | innertwo's›
+‹  | multi-line leaf payload›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errFmt
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+×
+×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errFmt
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+fmt innerone innertwo
+multi-elided-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  | -- this is innerone
+  | innertwo's
+  | multi-line leaf payload
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errFmt
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+‹  | -- this is innerone›
+‹  | innertwo's›
+‹  | multi-line leaf payload›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errFmt
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+×
+×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errFmt
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 fmt innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-fmt-via-network b/fmttests/testdata/format/wrap-fmt-via-network
index c152248..4ca1890 100644
--- a/fmttests/testdata/format/wrap-fmt-via-network
+++ b/fmttests/testdata/format/wrap-fmt-via-network
@@ -3138,6 +3138,956 @@ Type: "*fmttests.errFmt"
 Title: "outerthree: ×"
 (NO STACKTRACE)
 
+run
+fmt innerone innertwo
+multi-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+fmt innerone innertwo
+multi-elided-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 fmt innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-goerr b/fmttests/testdata/format/wrap-goerr
index fd97e94..1e5fb5f 100644
--- a/fmttests/testdata/format/wrap-goerr
+++ b/fmttests/testdata/format/wrap-goerr
@@ -2203,6 +2203,628 @@ Type: "*errors.errorString"
 Title: "outerthree: ×"
 (NO STACKTRACE)
 
+run
+goerr innerone innertwo
+multi-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.errorString
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.errorString
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.errorString
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+goerr innerone innertwo
+multi-elided-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.errorString
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.errorString
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.errorString
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 goerr innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-goerr-via-network b/fmttests/testdata/format/wrap-goerr-via-network
index 05a8e43..77c7cf6 100644
--- a/fmttests/testdata/format/wrap-goerr-via-network
+++ b/fmttests/testdata/format/wrap-goerr-via-network
@@ -2563,6 +2563,906 @@ Type: "*errors.errorString"
 Title: "outerthree: ×"
 (NO STACKTRACE)
 
+run
+goerr innerone innertwo
+multi-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errors.errorString
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errors.errorString
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errors.errorString
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+goerr innerone innertwo
+multi-elided-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.errorString{s:"innerone\ninnertwo"},
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errors.errorString
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errors.errorString
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errors.errorString
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 goerr innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-newf b/fmttests/testdata/format/wrap-newf
index 823f653..0737c0f 100644
--- a/fmttests/testdata/format/wrap-newf
+++ b/fmttests/testdata/format/wrap-newf
@@ -4641,6 +4641,784 @@ Title: "*errutil.leafError: outerthree: new-style ×\nvia *withstack.withStack"
 <path>:<lineno>:
    (github.com/cockroachdb/errors/fmttests.glob.)...funcNN...
 
+run
+newf innerone innertwo
+multi-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: new-style innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: new-style innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *withstack.withStack (11) *errutil.leafError
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: new-style ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: new-style ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ‹innerone›
+  | ‹innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *withstack.withStack (11) *errutil.leafError
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: new-style ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ×
+  | ×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *withstack.withStack (11) *errutil.leafError
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: new-style ×"
+(NO STACKTRACE)
+
+run
+newf innerone innertwo
+multi-elided-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: new-style innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: new-style innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *withstack.withStack (11) *errutil.leafError
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: new-style ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: new-style ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ‹innerone›
+  | ‹innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *withstack.withStack (11) *errutil.leafError
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: new-style ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ×
+  | ×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *withstack.withStack (11) *errutil.leafError
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: new-style ×"
+(NO STACKTRACE)
+
 run
 newf innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-newf-via-network b/fmttests/testdata/format/wrap-newf-via-network
index 57ebc9a..4c2ef5d 100644
--- a/fmttests/testdata/format/wrap-newf-via-network
+++ b/fmttests/testdata/format/wrap-newf-via-network
@@ -5474,6 +5474,1120 @@ Title: "*errutil.leafError: outerthree: new-style ×\nvia *withstack.withStack"
 <path>:<lineno>:
    (github.com/cockroachdb/errors/fmttests.glob.)...funcNN...
 
+run
+newf innerone innertwo
+multi-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: new-style innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: new-style innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueWrapper (11) *errutil.leafError
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: new-style ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: new-style ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ‹innerone›
+  | ‹innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueWrapper (11) *errutil.leafError
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: new-style ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ×
+  | ×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueWrapper (11) *errutil.leafError
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: new-style ×"
+(NO STACKTRACE)
+
+run
+newf innerone innertwo
+multi-elided-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: new-style innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: new-style innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueWrapper (11) *errutil.leafError
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: new-style ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: new-style ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ‹innerone›
+  | ‹innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueWrapper (11) *errutil.leafError
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: new-style ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (11) new-style ×
+  | ×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueWrapper (11) *errutil.leafError
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: new-style ×"
+(NO STACKTRACE)
+
 run
 newf innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-nofmt b/fmttests/testdata/format/wrap-nofmt
index c643809..863af37 100644
--- a/fmttests/testdata/format/wrap-nofmt
+++ b/fmttests/testdata/format/wrap-nofmt
@@ -2203,6 +2203,628 @@ Type: "*fmttests.errNoFmt"
 Title: "outerthree: ×"
 (NO STACKTRACE)
 
+run
+nofmt innerone innertwo
+multi-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errNoFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errNoFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errNoFmt
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errNoFmt
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errNoFmt
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+nofmt innerone innertwo
+multi-elided-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errNoFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &fmttests.errNoFmt{msg:"innerone\ninnertwo"},
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errNoFmt
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errNoFmt
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *fmttests.errNoFmt
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 nofmt innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-nofmt-via-network b/fmttests/testdata/format/wrap-nofmt-via-network
index e9e84c5..6227508 100644
--- a/fmttests/testdata/format/wrap-nofmt-via-network
+++ b/fmttests/testdata/format/wrap-nofmt-via-network
@@ -3138,6 +3138,956 @@ Type: "*fmttests.errNoFmt"
 Title: "outerthree: ×"
 (NO STACKTRACE)
 
+run
+nofmt innerone innertwo
+multi-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+nofmt innerone innertwo
+multi-elided-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", Extension:""},
+                        ReportablePayload: nil,
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 nofmt innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-pkgerr b/fmttests/testdata/format/wrap-pkgerr
index 3a351ff..9ca8b90 100644
--- a/fmttests/testdata/format/wrap-pkgerr
+++ b/fmttests/testdata/format/wrap-pkgerr
@@ -4471,6 +4471,772 @@ Title: "*errors.fundamental: outerthree: ×"
 <path>:<lineno>:
    (github.com/cockroachdb/errors/fmttests.glob.)...funcNN...
 
+run
+pkgerr innerone innertwo
+multi-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.fundamental{
+                    msg:   "innerone\ninnertwo",
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.fundamental{
+                    msg:   "innerone\ninnertwo",
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"included 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.fundamental
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func9›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.fundamental
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.fundamental
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+pkgerr innerone innertwo
+multi-elided-cause outerthree outerfour
+
+require (?s)outerthree.*outerfour.*
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.fundamental{
+                    msg:   "innerone\ninnertwo",
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errors.fundamental{
+                    msg:   "innerone\ninnertwo",
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"outerthree\nouterfour"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 1"},
+                    stack: &stack{...},
+                },
+                &withstack.withStack{
+                    cause: &errutil.leafError{msg:"elided 2"},
+                    stack: &stack{...},
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.fundamental
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+‹  | innertwo›
+‹  | github.com/cockroachdb/errors/fmttests.glob..func9›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective.func1›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirective›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.runTestInternal›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.RunTest›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk›
+‹  | <tab><path>:<lineno>›
+‹  | github.com/cockroachdb/datadriven.Walk.func1›
+‹  | <tab><path>:<lineno>›
+‹  | testing.tRunner›
+‹  | <tab><path>:<lineno>›
+‹  | runtime.goexit›
+‹  | <tab><path>:<lineno>›
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.fundamental
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8) attached stack trace
+  -- stack trace:
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | [...repeated from below...]
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+×
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *withstack.withStack (9) *errutil.leafError (10) *errors.fundamental
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 pkgerr innerone innertwo
 newfw outerthree outerfour
diff --git a/fmttests/testdata/format/wrap-pkgerr-via-network b/fmttests/testdata/format/wrap-pkgerr-via-network
index 5a4cae3..7af01eb 100644
--- a/fmttests/testdata/format/wrap-pkgerr-via-network
+++ b/fmttests/testdata/format/wrap-pkgerr-via-network
@@ -5346,6 +5346,1112 @@ Title: "*errors.fundamental: outerthree: ×"
 <path>:<lineno>:
    (github.com/cockroachdb/errors/fmttests.glob.)...funcNN...
 
+run
+pkgerr innerone innertwo
+multi-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/pkg/errors/*errors.fundamental",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/pkg/errors/*errors.fundamental", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/pkg/errors/*errors.fundamental",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/pkg/errors/*errors.fundamental", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"included 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: false,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: included 2: included 1: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: included 2: included 1: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: included 2: included 1: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: included 2: included 1: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) included 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) included 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: included 2: included 1: ×: outerthree: ×"
+(NO STACKTRACE)
+
+run
+pkgerr innerone innertwo
+multi-elided-cause outerthree outerfour
+opaque
+
+require (?s)outerthree.*outerfour.*innerone.*innertwo
+----
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/pkg/errors/*errors.fundamental",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/pkg/errors/*errors.fundamental", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+=====
+===== non-redactable formats
+=====
+== %#v
+&fmttests.errMultiCause{
+    causes: {
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueLeaf{
+                    msg:     "innerone\ninnertwo",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/pkg/errors/*errors.fundamental",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/pkg/errors/*errors.fundamental", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"outerthree\nouterfour"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "C",
+            elide: false,
+        },
+        &fmttests.errMultiCause{
+            causes: {
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 1"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+                &errbase.opaqueWrapper{
+                    cause:   &errutil.leafError{msg:"elided 2"},
+                    prefix:  "",
+                    details: errorspb.EncodedErrorDetails{
+                        OriginalTypeName:  "github.com/cockroachdb/errors/withstack/*withstack.withStack",
+                        ErrorTypeMark:     errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""},
+                        ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirective\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.runTestInternal\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.RunTest\n\<path>:<lineno>\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk\n\<path>:<lineno>\ngithub.com/cockroachdb/datadriven.Walk.func1\n\<path>:<lineno>\ntesting.tRunner\n\<path>:<lineno>\nruntime.goexit\n\<path>:<lineno>"},
+                        FullDetails:       (*types.Any)(nil),
+                    },
+                    messageType: 0,
+                },
+            },
+            msg:   "B",
+            elide: true,
+        },
+    },
+    msg:   "A",
+    elide: false,
+}
+== Error()
+A: B: C: outerthree
+outerfour: innerone
+innertwo
+== %v = Error(), good
+== %s = Error(), good
+== %q = quoted Error(), good
+== %x = hex Error(), good
+== %X = HEX Error(), good
+== %+v
+A: B: C: outerthree: innerone
+(1) A
+Wraps: (2) B
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) C
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) innerone
+  | innertwo
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+== %#v via Formattable() = %#v, good
+== %v via Formattable() = Error(), good
+== %s via Formattable() = %v via Formattable(), good
+== %q via Formattable() = quoted %v via Formattable(), good
+== %+v via Formattable() == %+v, good
+=====
+===== redactable formats
+=====
+== printed via redact Print(), ok - congruent with %v
+‹A›: ‹B›: ‹C›: outerthree
+outerfour: ‹innerone›
+‹innertwo›
+== printed via redact Printf() %v = Print(), good
+== printed via redact Printf() %s = Print(), good
+== printed via redact Printf() %q, refused - good
+== printed via redact Printf() %x, refused - good
+== printed via redact Printf() %X, refused - good
+== printed via redact Printf() %+v, ok - congruent with %+v
+‹A›: ‹B›: ‹C›: outerthree: ‹innerone›
+(1) ‹A›
+Wraps: (2) ‹B›
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ‹C›
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ‹innerone›
+  | ‹innertwo›
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+=====
+===== Sentry reporting
+=====
+== Message payload
+×: ×: ×: outerthree: ×
+(1) ×
+Wraps: (2) ×
+└─ Wraps: (3)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (4) elided 2
+└─ Wraps: (5)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (6) elided 1
+Wraps: (7) ×
+└─ Wraps: (8)
+  | (opaque error wrapper)
+  | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+  └─ Wraps: (9) outerthree
+  | outerfour
+└─ Wraps: (10) ×
+  | ×
+  |
+  | (opaque error leaf)
+  | type name: github.com/pkg/errors/*errors.fundamental
+  | reportable 0:
+  |
+  | github.com/cockroachdb/errors/fmttests.glob...funcNN...
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective.func1
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirective
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runDirectiveOrSubTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.runTestInternal
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.RunTest
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk
+  | <tab><path>:<lineno>
+  | github.com/cockroachdb/datadriven.Walk.func1
+  | <tab><path>:<lineno>
+  | testing.tRunner
+  | <tab><path>:<lineno>
+  | runtime.goexit
+  | <tab><path>:<lineno>
+Error types: (1) *fmttests.errMultiCause (2) *fmttests.errMultiCause (3) *errbase.opaqueWrapper (4) *errutil.leafError (5) *errbase.opaqueWrapper (6) *errutil.leafError (7) *fmttests.errMultiCause (8) *errbase.opaqueWrapper (9) *errutil.leafError (10) *errbase.opaqueLeaf
+-- report composition:
+*fmttests.errMultiCause
+== Extra "error types"
+github.com/cockroachdb/errors/fmttests/*fmttests.errMultiCause (*::)
+== Exception 1 (Module: "error domain: <none>")
+Type: "*fmttests.errMultiCause"
+Title: "×: ×: ×: outerthree: ×"
+(NO STACKTRACE)
+
 run
 pkgerr innerone innertwo
 newfw outerthree outerfour