Android 8.0 で java.lang.IndexOutOfBoundsException: setSpan (-1 ... -1) starts before 0

Previewのときからクラッシュレポートが来ていたけど、何が原因かわからず困っていた件が、やっと解決したので超久しぶりに日記に。
問題のエラー。

Fatal Exception: java.lang.IndexOutOfBoundsException: setSpan (-1 ... -1) starts before 0
       at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1314)
       at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:680)
       at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:672)
       at android.view.accessibility.AccessibilityNodeInfo.setText(AccessibilityNodeInfo.java:2474)
       at android.widget.TextView.onInitializeAccessibilityNodeInfoInternal(TextView.java:10357)
       at android.view.View.onInitializeAccessibilityNodeInfo(View.java:7307)
       at android.view.View.createAccessibilityNodeInfoInternal(View.java:7266)
       at android.view.View.createAccessibilityNodeInfo(View.java:7251)
       at android.view.accessibility.AccessibilityRecord.setSource(AccessibilityRecord.java:146)
       at android.view.accessibility.AccessibilityRecord.setSource(AccessibilityRecord.java:119)
       at android.view.View.onInitializeAccessibilityEventInternal(View.java:7203)
       at android.widget.TextView.onInitializeAccessibilityEventInternal(TextView.java:10338)
       at android.view.View.onInitializeAccessibilityEvent(View.java:7191)
       at android.view.View.sendAccessibilityEventUncheckedInternal(View.java:7053)
       at android.view.View.sendAccessibilityEventUnchecked(View.java:7038)
       at android.view.View$SendViewStateChangedAccessibilityEvent.run(View.java:26026)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6541)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

エラーが起こっている AccessibilityNodeInfo.java の中身。

    public void setText(CharSequence text) {
        enforceNotSealed();
        mOriginalText = text;
        // Replace any ClickableSpans in mText with placeholders
        if (text instanceof Spanned) {
            ClickableSpan[] spans =
                    ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
            if (spans.length > 0) {
                Spannable spannable = new SpannableStringBuilder(text);
                for (int i = 0; i < spans.length; i++) {
                    ClickableSpan span = spans[i];
                    if ((span instanceof AccessibilityClickableSpan)
                            || (span instanceof AccessibilityURLSpan)) {
                        // We've already done enough
                        break;
                    }
                    int spanToReplaceStart = spannable.getSpanStart(span);
                    int spanToReplaceEnd = spannable.getSpanEnd(span);
                    int spanToReplaceFlags = spannable.getSpanFlags(span);
                    spannable.removeSpan(span);
                    ClickableSpan replacementSpan = (span instanceof URLSpan)
                            ? new AccessibilityURLSpan((URLSpan) span)
                            : new AccessibilityClickableSpan(span.getId());
                    spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
                            spanToReplaceFlags);
                }
                mText = spannable;
                return;
            }
        }
        mText = (text == null) ? null : text.subSequence(0, text.length());
    }

text の ClickableSpan を AccessibilityClickableSpan に置き換えて返しているのだが、spannable.getSpanStart(span) の span が存在しないので -1 が返ってきてクラッシュしていた。
SpannableString と SpannableStringBuilder のわかりにくい違いとして、SpannableStringBuilder は NoCopySpan がコピーされないという違いがあるけど、これは関係なかった。
もう一つわかりにくい違いがあって、SpannableStringBuilder は setSpan() で長さ 0 の Span を設定しようとすると、設定されずに捨てられるということ。
SpannableStringBuilder#setSpan() で長さ0のClickableSpanを入れてしまっていたために、ここでクラッシュしていた。