{"record":{"id":"63d1a5ef5c128bfd","repo":"Crosstalk-Solutions/project-nomad","slug":"error-parsing-content-error-as-error-message","errorCode":null,"errorMessage":"Error parsing content: ${(error as Error).message}","messagePattern":"Error parsing content: (.+?)","errorType":"http","errorClass":"InternalServerErrorException","httpStatus":500,"severity":"error","filePath":"admin/app/services/docs_service.ts","lineNumber":61,"sourceCode":"  }\n\n  parse(content: string) {\n    try {\n      const ast = Markdoc.parse(content)\n      const config = this.getConfig()\n      const errors = Markdoc.validate(ast, config)\n\n      // Filter out attribute-undefined errors which may be caused by emojis and special characters\n      const criticalErrors = errors.filter((e) => e.error.id !== 'attribute-undefined')\n      if (criticalErrors.length > 0) {\n        logger.error('Markdoc validation errors:', errors.map((e) => JSON.stringify(e.error)).join(', '))\n        throw new Error('Markdoc validation failed')\n      }\n\n      return Markdoc.transform(ast, config)\n    } catch (error) {\n      logger.error('Error parsing Markdoc content:', error)\n      throw new InternalServerErrorException(`Error parsing content: ${(error as Error).message}`)\n    }\n  }\n\n  async parseFile(_filename: string) {\n    try {\n      if (!_filename) {\n        throw new Error('Filename is required')\n      }\n\n      const filename = _filename.endsWith('.md') ? _filename : `${_filename}.md`\n\n      // Prevent path traversal — resolved path must stay within the docs directory\n      const basePath = path.resolve(this.docsPath)\n      const fullPath = path.resolve(path.join(this.docsPath, filename))\n      if (!fullPath.startsWith(basePath + path.sep)) {\n        throw new Error('Invalid document slug')\n      }\n","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Crosstalk-Solutions/project-nomad/blob/0bd1c6f4f9888d577fe232de06ac144bb8337131/admin/app/services/docs_service.ts#L43-L79","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the appended original message — it names the Markdoc parse/validate failure (line number, tag name)","Lint the markdown with Markdoc.validate(ast) in a scratch script to enumerate errors before serving","Fix or strip the offending Markdoc tag/annotation in the content","If a custom tag is used, register it in the Markdoc config passed to parse","Pin/align the Markdoc version with the one the config was written for"],"exampleFix":"// before\nconst renderable = await docsService.parse('{% if x %}unclosed')\n\n// after\nconst ast = Markdoc.parse('{% if x %}unclosed')\nconst errors = Markdoc.validate(ast, config)\nif (errors.length) throw new Error(errors.map(e => e.error.id).join(', '))\nconst renderable = Markdoc.transform(ast, config)","handlingStrategy":"try-catch","validationCode":"import Markdoc from '@markdoc/markdoc'\nconst ast = Markdoc.parse(content)\nconst errors = Markdoc.validate(ast, config)\nif (errors.length) return { errors: errors.map(e => e.error.id) }","typeGuard":"const isParseError = (e: unknown): boolean =>\n  e instanceof InternalServerErrorException &&\n  (e.message.startsWith('Error parsing content:'))","tryCatchPattern":"try {\n  const renderable = await docsService.parse(content)\n} catch (e) {\n  if (e instanceof InternalServerErrorException) {\n    // surface suffix to editor for fixing the markdown\n    return new BadRequestException((e as Error).message)\n  }\n  throw e\n}","preventionTips":["Run Markdoc.validate on authored content in CI before publishing","Restrict custom tags to a documented allowlist registered in config","Pin the Markdoc version and test content fixtures on upgrades"],"tags":["markdoc","markdown","parsing","nestjs"],"backgroundTag":"markdown-parse-failed","analyzedSha":"0bd1c6f4f9888d577fe232de06ac144bb8337131","analyzedAt":"2026-08-27T05:34:15.424Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}