Skip to content

MermaidParser fails to initialize on Android: unescaped lone '}' in regex patterns (PatternSyntaxException in <clinit>) #114

Description

@bytemain

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions