yikart/AiToEarn · error · AppException

ResponseCode.ConfigEditorParseFailed

ResponseCode.ConfigEditorParseFailed

Error message

ConfigEditorParseFailed: error.message

What it means

When the config file content cannot be parsed as the format inferred from its extension (JSON.parse for .json, the 'yaml' package's parse for .yaml/.yml), parseConfig wraps the underlying parser error in AppException(ConfigEditorParseFailed) with the parser's message. The message field therefore carries the exact JSON/YAML syntax error, including position info for YAML.

Source

Thrown at project/aitoearn-backend/libs/config-editor/src/config-editor.service.ts:56

  private getConfigFileFormat(filePath: string): ConfigFileFormat {
    const lowerPath = filePath.toLowerCase()
    if (lowerPath.endsWith('.json')) {
      return ConfigFileFormat.Json
    }
    if (lowerPath.endsWith('.yaml') || lowerPath.endsWith('.yml')) {
      return ConfigFileFormat.Yaml
    }
    throw new AppException(ResponseCode.ConfigEditorUnsupportedFormat)
  }

  private parseConfig(content: string, format: ConfigFileFormat) {
    try {
      return format === ConfigFileFormat.Json
        ? JSON.parse(content)
        : parseYaml(content)
    }
    catch (error) {
      throw new AppException(
        ResponseCode.ConfigEditorParseFailed,
        error instanceof Error ? error.message : String(error),
      )
    }
  }

  private validateConfigValue(config: unknown): Record<string, unknown> {
    const schema = isZodDto(this.config.schema) ? this.config.schema.schema : this.config.schema
    if (!(schema instanceof z.ZodType)) {
      throw new AppException(ResponseCode.ConfigEditorValidationFailed)
    }

    const result = schema.safeParse(config)
    if (!result.success) {
      throw new AppException(ResponseCode.ConfigEditorValidationFailed, z.prettifyError(result.error))
    }
    return result.data as Record<string, unknown>
  }

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Read the nested message (e.g. 'Unexpected token } in JSON at position 42') and fix that exact spot in the config file
  2. Validate the file with a JSON/YAML linter or `node -e "JSON.parse(require('fs').readFileSync(path,'utf8'))"` before starting the app
  3. Verify the file extension matches the actual content format (real JSON in .json, real YAML in .yaml/.yml)
  4. Strip a UTF-8 BOM or re-save the file as plain UTF-8

Example fix

// before (config.json)
{ "port": 3000, }
// after
{ "port": 3000 }
Defensive patterns

Strategy: validation

Validate before calling

const content = await readFile(configPath, 'utf8')
if (configPath.endsWith('.json')) JSON.parse(content)
else parseYaml(content) // throws locally with the same parser message

Type guard

function isParseableJson(s: string): boolean {
  try { JSON.parse(s); return true } catch { return false }
}

Try / catch

try {
  await editor.getConfig()
} catch (e) {
  if (e instanceof AppException && e.code === ResponseCode.ConfigEditorParseFailed)
    logger.error(`Config file syntax error: ${e.message}`)
  throw e
}

Prevention

When it happens

Trigger: readConfigFile returned content that JSON.parse or parseYaml rejects: trailing commas in JSON, comments in JSON, single quotes in JSON keys, tabs in YAML, unclosed brackets/quotes, duplicated keys where the parser forbids them, or an empty file parsed as JSON.

Common situations: A hand-edited config file saved with a syntax error; a .json file that is actually YAML (or vice versa); a template/placeholder file never filled in; a CI step writing partial content before the app reads it; encoding issues (BOM) that break JSON.parse.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/c1e7097f004d27c7. Report an issue: GitHub.