@@ -349,66 +349,76 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) {
349349
350350 bufIsRedactable := false
351351
352- printDone := false
353- for _ , fn := range specialCases {
354- if handled , desiredShortening := fn (err , (* safePrinter )(s ), cause == nil /* leaf */ ); handled {
355- printDone = true
356- bufIsRedactable = true
357- if desiredShortening == nil {
358- // The error wants to elide the short messages from inner
359- // causes. Do it.
360- for i := range s .entries {
361- s .entries [i ].elideShort = true
362- }
352+ switch v := err .(type ) {
353+ case SafeFormatter :
354+ bufIsRedactable = true
355+ desiredShortening := v .SafeFormatError ((* safePrinter )(s ))
356+ if desiredShortening == nil {
357+ // The error wants to elide the short messages from inner
358+ // causes. Do it.
359+ for i := range s .entries {
360+ s .entries [i ].elideShort = true
363361 }
364- break
365362 }
366- }
367- if ! printDone {
368- switch v := err .(type ) {
369- case SafeFormatter :
370- bufIsRedactable = true
371- desiredShortening := v .SafeFormatError ((* safePrinter )(s ))
372- if desiredShortening == nil {
373- // The error wants to elide the short messages from inner
374- // causes. Do it.
375- for i := range s .entries {
376- s .entries [i ].elideShort = true
377- }
363+
364+ case Formatter :
365+ desiredShortening := v .FormatError ((* printer )(s ))
366+ if desiredShortening == nil {
367+ // The error wants to elide the short messages from inner
368+ // causes. Do it.
369+ for i := range s .entries {
370+ s .entries [i ].elideShort = true
378371 }
372+ }
379373
380- case Formatter :
381- desiredShortening := v .FormatError ((* printer )(s ))
382- if desiredShortening == nil {
383- // The error wants to elide the short messages from inner
384- // causes. Do it.
385- for i := range s .entries {
386- s .entries [i ].elideShort = true
387- }
374+ case fmt.Formatter :
375+ // We can only use a fmt.Formatter when both the following
376+ // conditions are true:
377+ // - when it is the leaf error, because a fmt.Formatter
378+ // on a wrapper also recurses.
379+ // - when it is not the outermost wrapper, because
380+ // the Format() method is likely to be calling FormatError()
381+ // to do its job and we want to avoid an infinite recursion.
382+ if ! isOutermost && cause == nil {
383+ v .Format (s , 'v' )
384+ if st , ok := err .(StackTraceProvider ); ok {
385+ // This is likely a leaf error from github/pkg/errors.
386+ // The thing probably printed its stack trace on its own.
387+ seenTrace = true
388+ // We'll subsequently simplify stack traces in wrappers.
389+ s .lastStack = st .StackTrace ()
388390 }
391+ } else {
392+ s .formatSimple (err , cause )
393+ }
389394
390- case fmt.Formatter :
391- // We can only use a fmt.Formatter when both the following
392- // conditions are true:
393- // - when it is the leaf error, because a fmt.Formatter
394- // on a wrapper also recurses.
395- // - when it is not the outermost wrapper, because
396- // the Format() method is likely to be calling FormatError()
397- // to do its job and we want to avoid an infinite recursion.
398- if ! isOutermost && cause == nil {
399- v .Format (s , 'v' )
400- if st , ok := err .(StackTraceProvider ); ok {
401- // This is likely a leaf error from github/pkg/errors.
402- // The thing probably printed its stack trace on its own.
403- seenTrace = true
404- // We'll subsequently simplify stack traces in wrappers.
405- s .lastStack = st .StackTrace ()
395+ default :
396+ // Handle the special case overrides for context.Canceled,
397+ // os.PathError, etc for which we know how to extract some safe
398+ // strings.
399+ //
400+ // We need to do this in the `default` branch, instead of doing
401+ // this above the switch, because the special handler could call a
402+ // .Error() that delegates its implementation to fmt.Formatter,
403+ // errors.Safeformatter or errors.Formattable, which brings us
404+ // back to this method in a call cycle. So we need to handle the
405+ // various interfaces first.
406+ printDone := false
407+ for _ , fn := range specialCases {
408+ if handled , desiredShortening := fn (err , (* safePrinter )(s ), cause == nil /* leaf */ ); handled {
409+ printDone = true
410+ bufIsRedactable = true
411+ if desiredShortening == nil {
412+ // The error wants to elide the short messages from inner
413+ // causes. Do it.
414+ for i := range s .entries {
415+ s .entries [i ].elideShort = true
416+ }
406417 }
407- } else {
408- s .formatSimple (err , cause )
418+ break
409419 }
410-
411- default :
420+ }
421+ if ! printDone {
412422 // If the error did not implement errors.Formatter nor
413423 // fmt.Formatter, but it is a wrapper, still attempt best effort:
414424 // print what we can at this level.
0 commit comments