Symptom
On Android, every mermaid diagram falls back to the plain fenced code block. In the consumer (botiverse/mobile, SlockMermaidDiagramBlock.android.kt) the first call into MermaidParser.parse(...) throws and is swallowed by a catch (Throwable):
java.lang.ExceptionInInitializerError
Caused by: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 42
at build.raft.mermaid.core.MermaidParser.<clinit>(MermaidParser.kt:2491)
(captured on emulator-5558, Android 34, by 沈括; independently reproduced on a hosted emulator via SLOCK_MERMAID_DIAG logging.)
Because the failure is in the object's static initializer, no diagram type works on Android — sequence diagrams fail the same way. JVM unit tests pass because OpenJDK's regex accepts the pattern; Android's java.util.regex is ICU-based and rejects an unescaped lone } that is not a quantifier.
Offending patterns (v0.1.2 = 0a7250f; still present at 89aada5)
MermaidParser.kt:2491 — SWIMLANE_DECISION_NODE = Regex("^($IDENTIFIER)\\{([^}\\r\\n]+)}$") — trailing } unescaped
MermaidParser.kt:2516 — RADAR_CURVE = Regex("...\\{([^{}]*)}$") — trailing } unescaped
ER_RELATIONSHIP (same shape, per 沈括)
- Multi-line
Regex(...) constructions were not covered by a single-line grep; please sweep every pattern for an unescaped } outside {n,m} quantifiers.
Note: [^]…] (literal ] first in a negated class) is accepted by ICU — SWIMLANE_LANE at line 2487 initializes before 2491 and does not fail.
Fix
Escape the literal closing braces (\\}); semantics are unchanged on the JVM. Suggested guard: an Android instrumented test that compiles every pattern, or at minimum a commonTest that round-trips each pattern string through Regex(...) on all targets, since Kotlin/Native (iOS/OHOS) uses yet another engine and has not been verified either way.
Consumer-side detector
botiverse/mobile now has three nightly visual cases (components.thread.message-row.md-mermaid-{flowchart,sequence,invalid-fallback}, PR #2533). They currently capture the fallback; they will flip to a drawn diagram once a fixed release (0.1.3 / 0.1.3-ohos) lands and mobile bumps.
Raft thread: #raft-mobile-reconcile:d95f0384 (2026-09-21).
Symptom
On Android, every mermaid diagram falls back to the plain fenced code block. In the consumer (
botiverse/mobile,SlockMermaidDiagramBlock.android.kt) the first call intoMermaidParser.parse(...)throws and is swallowed by acatch (Throwable):(captured on emulator-5558, Android 34, by 沈括; independently reproduced on a hosted emulator via
SLOCK_MERMAID_DIAGlogging.)Because the failure is in the object's static initializer, no diagram type works on Android — sequence diagrams fail the same way. JVM unit tests pass because OpenJDK's regex accepts the pattern; Android's
java.util.regexis ICU-based and rejects an unescaped lone}that is not a quantifier.Offending patterns (v0.1.2 = 0a7250f; still present at 89aada5)
MermaidParser.kt:2491—SWIMLANE_DECISION_NODE = Regex("^($IDENTIFIER)\\{([^}\\r\\n]+)}$")— trailing}unescapedMermaidParser.kt:2516—RADAR_CURVE = Regex("...\\{([^{}]*)}$")— trailing}unescapedER_RELATIONSHIP(same shape, per 沈括)Regex(...)constructions were not covered by a single-line grep; please sweep every pattern for an unescaped}outside{n,m}quantifiers.Note:
[^]…](literal]first in a negated class) is accepted by ICU —SWIMLANE_LANEat line 2487 initializes before 2491 and does not fail.Fix
Escape the literal closing braces (
\\}); semantics are unchanged on the JVM. Suggested guard: an Android instrumented test that compiles every pattern, or at minimum acommonTestthat round-trips each pattern string throughRegex(...)on all targets, since Kotlin/Native (iOS/OHOS) uses yet another engine and has not been verified either way.Consumer-side detector
botiverse/mobilenow has three nightly visual cases (components.thread.message-row.md-mermaid-{flowchart,sequence,invalid-fallback}, PR #2533). They currently capture the fallback; they will flip to a drawn diagram once a fixed release (0.1.3 / 0.1.3-ohos) lands and mobile bumps.Raft thread: #raft-mobile-reconcile:d95f0384 (2026-09-21).