hcengineering/platform · error

No info for mark ${mark.type}

Error message

No info for mark ${mark.type}

What it means

markString() resolves the open/close Markdown syntax for a mark from this.marks. When a mark has no explicit attrs.marker and no registered mark info, the serializer does not know how to translate it and throws. This guards against emitting Markdown with broken/missing emphasis formatting.

Source

Thrown at foundations/core/packages/text-markdown/src/serializer.ts:875

    return wrap[0] + str + wrap[1]
  }

  // :: (string, number) → string
  // Repeat the given string `n` times.
  repeat (str: string, n: number): string {
    let out = ''
    for (let i = 0; i < n; i++) out += str
    return out
  }

  // : (Mark, bool, string?) → string
  // Get the markdown string for a given opening or closing mark.
  markString (mark: MarkupMark, open: boolean, parent: MarkupNode, index: number): string {
    let value = mark.attrs?.marker
    if (value === undefined) {
      const info = this.marks[mark.type]
      if (info == null) {
        throw new Error(`No info for mark ${mark.type}`)
      }
      value = open ? info.open : info.close
    }
    return typeof value === 'string' ? value : (value(this, mark, parent, index) ?? '')
  }
}

function makeQuery (obj: Record<string, string | number | boolean | null | undefined>): string {
  return Object.keys(obj)
    .filter((it) => it[1] != null)
    .map(function (k) {
      return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k] as string | number | boolean)
    })
    .join('&')
}

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Register the mark in the serializer's marks table with open/close strings or functions
  2. Set an attrs.marker on the mark so markString can use it directly
  3. Strip unsupported marks from the document before serialization

Example fix

// before
marks: {} // 'highlight' mark missing
// after
marks: { highlight: { open: '==', close: '==' } }
Defensive patterns

Strategy: validation

Validate before calling

for (const m of node.marks ?? []) {
  if (!state.marks[m.type] && m.attrs?.marker === undefined) {
    throw new Error(`mark ${m.type} has no markdown serialization`)
  }
}

Type guard

function hasMarkInfo(state: { marks: Record<string, unknown> }, mark: { type: string; attrs?: { marker?: string } }): boolean {
  return mark.attrs?.marker !== undefined || state.marks[mark.type] != null
}

Try / catch

try {
  md = state.markString(mark, open, parent, index)
} catch (e) {
  if (e.message.startsWith('No info for mark')) {
    return '' // or strip the mark
  }
  throw e
}

Prevention

When it happens

Trigger: Serializing a document containing a mark type (e.g. a custom annotation or link variant) that is not registered in the Markdown state's marks table and carries no marker attribute.

Common situations: Custom marks added by extensions, marks from pasted rich text, schema changes adding new mark types without Markdown serializer support.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/1f356ce4f7687d95. Report an issue: GitHub.