yikart/AiToEarn · error · AppException
ResponseCode.ConfigEditorValidationFailed
ResponseCode.ConfigEditorValidationFailed
Error message
ConfigEditorValidationFailed
What it means
validateConfigValue requires the ConfigEditorConfig.schema to be a usable Zod schema — either a Zod DTO (from createZodDto, unwrapped via isZodDto) or a raw z.ZodType instance. If after that unwrapping the value is not a z.ZodType, the library cannot validate anything and throws ConfigEditorValidationFailed with no message.
Source
Thrown at project/aitoearn-backend/libs/config-editor/src/config-editor.service.ts:66
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>
}
private serializeConfig(config: Record<string, unknown>, format: ConfigFileFormat) {
if (format === ConfigFileFormat.Json) {
return `${JSON.stringify(config, null, 2)}\n`
}
return stringifyYaml(config)
}
private async readConfigFile(configPath: string) {
try {View on GitHub (pinned to d3aa8bea5b)
Solutions
- Pass a zod schema (z.object({...})) or a createZodDto(...) result as the schema option
- Check `pnpm why zod` / lockfile for duplicate zod versions; dedupe so the same zod instance is shared with @yikart/common
- If using a ZodDto class, make sure it was created with createZodDto so isZodDto recognizes it
- Log/inspect the schema value at registration to confirm it is defined and non-null
Example fix
// before
ConfigEditorModule.register({ configPath: 'config/app.yaml', schema: AppConfig }) // plain interface
// after
const AppConfigSchema = z.object({ port: z.number() })
ConfigEditorModule.register({ configPath: 'config/app.yaml', schema: AppConfigSchema }) Defensive patterns
Strategy: validation
Validate before calling
import { z } from 'zod'
if (!(schema instanceof z.ZodType) && !isZodDto(schema))
throw new Error('ConfigEditor schema must be a zod schema or createZodDto result') Type guard
function isUsableSchema(s: unknown): s is z.ZodType {
const inner = isZodDto(s) ? s.schema : s
return inner instanceof z.ZodType
} Try / catch
try {
editor.validateConfig(payload)
} catch (e) {
if (e instanceof AppException && e.code === ResponseCode.ConfigEditorValidationFailed && !e.message)
logger.error('Schema itself is not a ZodType — fix module registration')
throw e
} Prevention
- Only pass zod schemas or createZodDto classes as schema
- Dedupe zod versions (`pnpm why zod`) so instanceof checks hold
- Never pass plain TS interfaces or class-validator classes as schema
- Add a unit test asserting the module registers with a valid schema
When it happens
Trigger: ConfigEditorModule is registered with a schema that is neither a Zod DTO nor a z.ZodType: e.g. a plain object, a class without createZodDto, a JSON-Schema/class-validator schema, undefined/null schema, or a zod version mismatch making `instanceof z.ZodType` fail across duplicate zod copies.
Common situations: Passing a plain TS interface (types vanish at runtime); passing a class decorated for class-validator instead of a Zod DTO; importing z from two different zod package instances (v3 vs v4 or duplicate installs) so instanceof fails; forgetting the schema option entirely.
Related errors
- InvalidModel
- Zod validation error (issues + input)
- errors.validateFailed
- No subtitle entries in response
- No response from Gemini
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/b10fccb2fb5ebe60.
Report an issue: GitHub.