yikart/AiToEarn · critical · AppException
ResponseCode.ConfigEditorWriteFailed
ResponseCode.ConfigEditorWriteFailed
Error message
ConfigEditorWriteFailed: error.message
What it means
writeConfigFile failed when saveConfig tried to persist the serialized config with fs writeFile (utf-8). The Node error is rethrown as AppException(ConfigEditorWriteFailed) with error.message, typically ENOSPC (disk full), EACCES (no write permission), EROFS (read-only filesystem), or ENOENT (parent directory missing).
Source
Thrown at project/aitoearn-backend/libs/config-editor/src/config-editor.service.ts:100
private async readConfigFile(configPath: string) {
try {
return await readFile(configPath, 'utf-8')
}
catch (error) {
throw new AppException(
ResponseCode.ConfigEditorReadFailed,
error instanceof Error ? error.message : String(error),
)
}
}
private async writeConfigFile(configPath: string, content: string) {
try {
await writeFile(configPath, content, 'utf-8')
}
catch (error) {
throw new AppException(
ResponseCode.ConfigEditorWriteFailed,
error instanceof Error ? error.message : String(error),
)
}
}
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Read error.message: ENOSPC → free disk space; EACCES → chown/chmod the file or run as a user with write access; EROFS/ENOENT → make the mount writable or recreate the directory
- Ensure the config file's volume is mounted rw, not :ro, in docker-compose/Kubernetes
- Give the container's runtime user ownership of the config directory (chown -R node:node /app/config)
- If the config is intentionally immutable (ConfigMap), stop exposing saveConfig / make the editor read-only instead of writing
Example fix
// before (docker-compose.yml) volumes: - ./config/app.yaml:/app/config/app.yaml:ro // after volumes: - ./config/app.yaml:/app/config/app.yaml:rw
Defensive patterns
Strategy: try-catch
Validate before calling
import { accessSync, constants } from 'node:fs'
try { accessSync(resolvedPath, constants.W_OK) } catch { /* not writable — surface before editing */ } Try / catch
try {
await editor.saveConfig(newConfig)
} catch (e) {
if (e instanceof AppException && e.code === ResponseCode.ConfigEditorWriteFailed) {
if (e.message.includes('EROFS')) logger.error('Config filesystem is read-only')
if (e.message.includes('ENOSPC')) logger.error('Disk full')
if (e.message.includes('EACCES')) logger.error('No write permission')
}
throw e
} Prevention
- Mount config volumes as rw if the editor must save
- Grant the runtime user write access (chown/chmod) to the config directory
- Do not expose saveConfig when configs are intentionally immutable (ConfigMap)
- Monitor disk space on hosts where config edits are allowed
When it happens
Trigger: saveConfig() is called and the resolved configPath is in a read-only container filesystem or read-only volume mount, the process user lacks write permission, the disk is full, or the config file was deleted along with its directory after startup.
Common situations: Kubernetes/Docker mounts with the config baked as read-only (common for ConfigMap mounts); running as a non-root user in a container that owns no writable path; tmpfs full; disk quota exceeded; PM2 restart with a cwd whose config dir no longer exists.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/03a49e10637393c1.
Report an issue: GitHub.