{"record":{"id":"4fa96b2359c73788","repo":"Crosstalk-Solutions/project-nomad","slug":"error-parsing-file-error-as-error-message","errorCode":null,"errorMessage":"Error parsing file: ${(error as Error).message}","messagePattern":"Error parsing file: (.+?)","errorType":"http","errorClass":"InternalServerErrorException","httpStatus":500,"severity":"error","filePath":"admin/app/services/docs_service.ts","lineNumber":92,"sourceCode":"      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\n      const fileExists = await getFileStatsIfExists(fullPath)\n      if (!fileExists) {\n        throw new Error(`File not found: ${filename}`)\n      }\n\n      const fileStream = await getFile(fullPath, 'stream')\n      if (!fileStream) {\n        throw new Error(`Failed to read file stream: ${filename}`)\n      }\n      const content = await streamToString(fileStream)\n      return this.parse(content)\n    } catch (error) {\n      throw new InternalServerErrorException(`Error parsing file: ${(error as Error).message}`)\n    }\n  }\n\n  private static readonly TITLE_OVERRIDES: Record<string, string> = {\n    'faq': 'FAQ',\n    'community-add-ons': 'Community Add-Ons',\n  }\n\n  private prettify(filename: string) {\n    const slug = filename.replace(/\\.md$/, '')\n    if (DocsService.TITLE_OVERRIDES[slug]) {\n      return DocsService.TITLE_OVERRIDES[slug]\n    }\n    // Remove hyphens, underscores, and file extension\n    const cleaned = slug.replace(/_/g, ' ').replace(/-/g, ' ')\n    // Convert to Title Case\n    const titleCased = cleaned.replace(/\\b\\w/g, (char) => char.toUpperCase())\n    return titleCased.charAt(0).toUpperCase() + titleCased.slice(1)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/Crosstalk-Solutions/project-nomad/blob/0bd1c6f4f9888d577fe232de06ac144bb8337131/admin/app/services/docs_service.ts#L74-L110","documentation":"Catch-all wrapper in DocsService.parseFile: every failure inside the method (missing filename, invalid slug, file not found, stream failure, or a Markdoc parse error from this.parse) is rethrown as InternalServerErrorException('Error parsing file: <original message>'). The original cause is only visible in the suffixed message.","triggerScenarios":"Any of the inner guards firing, or parse() throwing on malformed markdown once the file content reaches it; the caller sees only this wrapper with the root cause appended after the colon.","commonSituations":"Debugging is slowed because 500s hide the specific cause; commonly the suffix is 'File not found', 'Invalid document slug', or 'Markdoc validation failed'.","solutions":["Parse the suffix after 'Error parsing file: ' to route to the right fix (see the specific inner errors 62-65, 61)","Log the full error server-side (logger already captures it) and reproduce with the exact slug","Improve the wrapper to rethrow NestJS HttpExceptions unchanged so 404/400-class causes keep their status"],"exampleFix":"// before\n} catch (error) {\n  throw new InternalServerErrorException(`Error parsing file: ${(error as Error).message}`)\n}\n\n// after\n} catch (error) {\n  if (error instanceof HttpException) throw error\n  throw new InternalServerErrorException(`Error parsing file: ${(error as Error).message}`)\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight: existence + readability avoids most wrapped causes\nconst p = path.join(docsPath, `${slug}.md`)\nif (!(await getFileStatsIfExists(p))) throw new NotFoundException(slug)","typeGuard":"const isDocsParseException = (e: unknown): e is InternalServerErrorException =>\n  e instanceof InternalServerErrorException && e.message.startsWith('Error parsing file:')","tryCatchPattern":"try {\n  const doc = await docsService.parseFile(slug)\n} catch (e) {\n  const cause = (e as Error).message.replace('Error parsing file: ', '')\n  if (cause.startsWith('File not found')) throw new NotFoundException(cause)\n  if (cause === 'Invalid document slug') throw new BadRequestException(cause)\n  throw e\n}","preventionTips":["Map the unwrapped suffix to proper HTTP statuses at the controller","Pre-validate slug and file existence before calling parseFile","In app code, rethrow HttpException unchanged in catch blocks"],"tags":["error-wrapping","nestjs","docs"],"backgroundTag":"generic-error-wrapper","analyzedSha":"0bd1c6f4f9888d577fe232de06ac144bb8337131","analyzedAt":"2026-08-27T05:34:15.424Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}