Crosstalk-Solutions/project-nomad · error · InternalServerErrorException

Error parsing content: ${(error as Error).message}

Error message

Error parsing content: ${(error as Error).message}

What it means

Generic wrapper thrown by DocsService.parse when Markdoc parsing/validation of markdown content fails unexpectedly. The method validates the Markdoc AST and transforms it; any exception during tokenize, validate, or transform is caught, logged, and rethrown as an InternalServerErrorException with the original message appended.

Source

Thrown at admin/app/services/docs_service.ts:61

  }

  parse(content: string) {
    try {
      const ast = Markdoc.parse(content)
      const config = this.getConfig()
      const errors = Markdoc.validate(ast, config)

      // Filter out attribute-undefined errors which may be caused by emojis and special characters
      const criticalErrors = errors.filter((e) => e.error.id !== 'attribute-undefined')
      if (criticalErrors.length > 0) {
        logger.error('Markdoc validation errors:', errors.map((e) => JSON.stringify(e.error)).join(', '))
        throw new Error('Markdoc validation failed')
      }

      return Markdoc.transform(ast, config)
    } catch (error) {
      logger.error('Error parsing Markdoc content:', error)
      throw new InternalServerErrorException(`Error parsing content: ${(error as Error).message}`)
    }
  }

  async parseFile(_filename: string) {
    try {
      if (!_filename) {
        throw new Error('Filename is required')
      }

      const filename = _filename.endsWith('.md') ? _filename : `${_filename}.md`

      // Prevent path traversal — resolved path must stay within the docs directory
      const basePath = path.resolve(this.docsPath)
      const fullPath = path.resolve(path.join(this.docsPath, filename))
      if (!fullPath.startsWith(basePath + path.sep)) {
        throw new Error('Invalid document slug')
      }

View on GitHub (pinned to 0bd1c6f4f9)

Solutions

  1. Read the appended original message — it names the Markdoc parse/validate failure (line number, tag name)
  2. Lint the markdown with Markdoc.validate(ast) in a scratch script to enumerate errors before serving
  3. Fix or strip the offending Markdoc tag/annotation in the content
  4. If a custom tag is used, register it in the Markdoc config passed to parse
  5. Pin/align the Markdoc version with the one the config was written for

Example fix

// before
const renderable = await docsService.parse('{% if x %}unclosed')

// after
const ast = Markdoc.parse('{% if x %}unclosed')
const errors = Markdoc.validate(ast, config)
if (errors.length) throw new Error(errors.map(e => e.error.id).join(', '))
const renderable = Markdoc.transform(ast, config)
Defensive patterns

Strategy: try-catch

Validate before calling

import Markdoc from '@markdoc/markdoc'
const ast = Markdoc.parse(content)
const errors = Markdoc.validate(ast, config)
if (errors.length) return { errors: errors.map(e => e.error.id) }

Type guard

const isParseError = (e: unknown): boolean =>
  e instanceof InternalServerErrorException &&
  (e.message.startsWith('Error parsing content:'))

Try / catch

try {
  const renderable = await docsService.parse(content)
} catch (e) {
  if (e instanceof InternalServerErrorException) {
    // surface suffix to editor for fixing the markdown
    return new BadRequestException((e as Error).message)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling parse() (directly or via parseFile/_parseContainerConfig/parseZimEntries) with malformed markdown: unclosed tags/annotations, invalid Markdoc syntax, unsupported nodes, or a custom config that throws during render-node transformation.

Common situations: User-authored docs with invalid Markdoc tags ({% if %} without {% /if %}), custom tag names not registered in config, content pasted from rich editors containing control characters, Markdoc version changes altering the AST schema.

Related errors


AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27). Data as JSON: /api/errors/63d1a5ef5c128bfd. Report an issue: GitHub.