{"record":{"id":"dd36dacfaefd15f7","repo":"yikart/AiToEarn","slug":"responsecode-configeditorreadfailed","errorCode":"ResponseCode.ConfigEditorReadFailed","errorMessage":"ConfigEditorReadFailed: error.message","messagePattern":"ConfigEditorReadFailed: error\\.message","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"critical","filePath":"project/aitoearn-backend/libs/config-editor/src/config-editor.service.ts","lineNumber":88,"sourceCode":"    if (!result.success) {\n      throw new AppException(ResponseCode.ConfigEditorValidationFailed, z.prettifyError(result.error))\n    }\n    return result.data as Record<string, unknown>\n  }\n\n  private serializeConfig(config: Record<string, unknown>, format: ConfigFileFormat) {\n    if (format === ConfigFileFormat.Json) {\n      return `${JSON.stringify(config, null, 2)}\\n`\n    }\n    return stringifyYaml(config)\n  }\n\n  private async readConfigFile(configPath: string) {\n    try {\n      return await readFile(configPath, 'utf-8')\n    }\n    catch (error) {\n      throw new AppException(\n        ResponseCode.ConfigEditorReadFailed,\n        error instanceof Error ? error.message : String(error),\n      )\n    }\n  }\n\n  private async writeConfigFile(configPath: string, content: string) {\n    try {\n      await writeFile(configPath, content, 'utf-8')\n    }\n    catch (error) {\n      throw new AppException(\n        ResponseCode.ConfigEditorWriteFailed,\n        error instanceof Error ? error.message : String(error),\n      )\n    }\n  }\n}","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/libs/config-editor/src/config-editor.service.ts#L70-L106","documentation":"readConfigFile failed to read the resolved config file (resolve(process.cwd(), configPath)) with fs readFile in utf-8 mode. The underlying Node error (ENOENT, EACCES, EISDIR, etc.) is wrapped into AppException(ConfigEditorReadFailed) with error.message preserved, so the message names the real filesystem cause.","triggerScenarios":"The file at configPath does not exist (ENOENT), the process lacks read permission (EACCES), configPath resolves to a directory (EISDIR), or the path is wrong relative to the process's cwd (containers/PM2 often change cwd).","commonSituations":"Config file not mounted/copied into a Docker image or volume; wrong relative path because the app starts from a different cwd under pm2/Nx; file permissions after a non-root container user change; a typo in configPath; the config file deleted between restarts because it lived only in a container layer.","solutions":["Read error.message: fix the exact cause — create the missing file (ENOENT), fix permissions with chmod/chown (EACCES), or point configPath at a file not a directory (EISDIR)","Use an absolute configPath (or verify process.cwd() at startup) so the resolve() lands where the file actually is","In Docker/PM2, mount or COPY the config file and confirm with `ls` inside the container/pwd context","Check the container user can read the file: run `whoami` and `stat <path>` in the same environment"],"exampleFix":"// before\nConfigEditorModule.register({ configPath: 'config/app.yaml', schema: S })\n// after (cwd-independent)\nConfigEditorModule.register({ configPath: '/app/config/app.yaml', schema: S })","handlingStrategy":"try-catch","validationCode":"import { accessSync, constants } from 'node:fs'\ntry { accessSync(resolvedPath, constants.R_OK) } catch (e) { /* fail fast: file missing/unreadable */ }","typeGuard":null,"tryCatchPattern":"try {\n  await editor.getConfig()\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.ConfigEditorReadFailed) {\n    if (e.message.includes('ENOENT')) logger.error(`Config file missing: ${e.message}`)\n    if (e.message.includes('EACCES')) logger.error(`Config file unreadable: ${e.message}`)\n  }\n  throw e\n}","preventionTips":["Prefer absolute configPath so it is independent of process.cwd()","Mount/COPY the config file into Docker images and verify with ls at startup","Check file readability for the runtime user, especially non-root containers","Keep config files on persistent volumes, not ephemeral container layers"],"tags":["filesystem","config","io","enoent"],"backgroundTag":"file-not-found","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}