moeru-ai/airi · warning

Failed to process markdown with syntax highlighting, using f

Error message

Failed to process markdown with syntax highlighting, using fallback:

What it means

The async markdown upgrade path (await process(content) followed by DOMPurify.sanitize) threw — most often inside the syntax-highlighting pipeline. The synchronous processSync render was already applied by processContent, and the catch leaves processedContent at that sync result, which is the 'fallback' the message refers to. Stale writes are prevented by the requestId === processRequestId check, so the un-highlighted render simply stays.

Source

Thrown at packages/stage-ui/src/components/markdown/markdown-renderer.vue:26

interface Props {
  content: string
  class?: string | string[]
}

const props = defineProps<Props>()

const processedContent = ref('')
const { process, processSync } = useMarkdown()
let processRequestId = 0

async function processRichContent(content: string, requestId: number) {
  try {
    const result = DOMPurify.sanitize(await process(content))
    if (requestId === processRequestId)
      processedContent.value = result
  }
  catch (error) {
    console.warn('Failed to process markdown with syntax highlighting, using fallback:', error)
  }
}

function processContent() {
  const content = props.content
  const requestId = ++processRequestId

  if (!content) {
    processedContent.value = ''
    return
  }

  try {
    processedContent.value = DOMPurify.sanitize(processSync(content))
  }
  catch (error) {
    console.warn('Failed to process markdown:', error)
    processedContent.value = ''

View on GitHub (pinned to 677329427f)

Solutions

  1. Inspect the logged error: unknown language ids and bundle load failures are the usual causes
  2. Normalize or strip language ids on code fences before processing
  3. Bundle the highlighter locally instead of dynamic imports that can fail offline
  4. Keep the sync fallback explicit: on catch, assign DOMPurify.sanitize(processSync(content)) guarded by the requestId check

Example fix

// before
catch (error) {
  console.warn('Failed to process markdown with syntax highlighting, using fallback:', error)
}

// after: make the promised fallback explicit (sync render stays, highlighted one retries next watch)
catch (error) {
  console.warn('Failed to process markdown with syntax highlighting, using fallback:', error)
  if (requestId === processRequestId)
    processedContent.value = DOMPurify.sanitize(processSync(content))
}
Defensive patterns

Strategy: fallback

Try / catch

try {
  const result = DOMPurify.sanitize(await process(content))
  if (requestId === processRequestId) processedContent.value = result
}
catch (error) {
  console.warn('Failed to process markdown with syntax highlighting, using fallback:', error)
  // sync render (processSync) already filled processedContent; it stays as the fallback
}

Prevention

When it happens

Trigger: Code fence with an unknown or misspelled language id; the highlighter bundle failing to load (offline dynamic import, HMR teardown); very large inputs failing in the async path.

Common situations: Chat messages containing code blocks with exotic languages; dev-server offline for the highlighter bundle; very long pasted documents.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/61296e6f13116faf. Report an issue: GitHub.