OpenAEC-Foundation

erpnext-code-validator

"Intelligent agent for validating ERPNext/Frappe code against best practices and common pitfalls. Use when reviewing generated code, checking for errors before deployment, or validating code quality. Triggers: review this code, check my script, validate before deployment, is this correct, find bugs, check for errors, will this work."

OpenAEC-Foundation 195 57 Updated 9mo ago

Resources

1
GitHub

Install

npx skillscat add openaec-foundation/erpnext-anthropic-claude-development-skill-package/erpnext-code-validator

Install via the SkillsCat registry.

SKILL.md

ERPNext Code Validator Agent

This agent validates ERPNext/Frappe code against established patterns, common pitfalls, and version compatibility requirements.

Purpose: Catch errors BEFORE deployment, not after

When to Use This Agent

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ CODE VALIDATION TRIGGERS                                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                     โ”‚
โ”‚ โ–บ Code has been generated and needs review                          โ”‚
โ”‚   "Check this Server Script before I save it"                       โ”‚
โ”‚   โ””โ”€โ”€ USE THIS AGENT                                                โ”‚
โ”‚                                                                     โ”‚
โ”‚ โ–บ Code is causing errors                                            โ”‚
โ”‚   "Why isn't this working?"                                         โ”‚
โ”‚   โ””โ”€โ”€ USE THIS AGENT                                                โ”‚
โ”‚                                                                     โ”‚
โ”‚ โ–บ Pre-deployment validation                                         โ”‚
โ”‚   "Is this production-ready?"                                       โ”‚
โ”‚   โ””โ”€โ”€ USE THIS AGENT                                                โ”‚
โ”‚                                                                     โ”‚
โ”‚ โ–บ Code review for best practices                                    โ”‚
โ”‚   "Can this be improved?"                                           โ”‚
โ”‚   โ””โ”€โ”€ USE THIS AGENT                                                โ”‚
โ”‚                                                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Validation Workflow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    CODE VALIDATOR WORKFLOW                          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                     โ”‚
โ”‚  STEP 1: IDENTIFY CODE TYPE                                         โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                         โ”‚
โ”‚  โ€ข Client Script (JavaScript)                                       โ”‚
โ”‚  โ€ข Server Script (Python sandbox)                                   โ”‚
โ”‚  โ€ข Controller (Python full)                                         โ”‚
โ”‚  โ€ข hooks.py configuration                                           โ”‚
โ”‚  โ€ข Jinja template                                                   โ”‚
โ”‚  โ€ข Whitelisted method                                               โ”‚
โ”‚                                                                     โ”‚
โ”‚  STEP 2: RUN TYPE-SPECIFIC CHECKS                                   โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                  โ”‚
โ”‚  โ€ข Apply checklist for identified code type                         โ”‚
โ”‚  โ€ข Check syntax patterns                                            โ”‚
โ”‚  โ€ข Verify API usage                                                 โ”‚
โ”‚                                                                     โ”‚
โ”‚  STEP 3: CHECK UNIVERSAL RULES                                      โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                     โ”‚
โ”‚  โ€ข Error handling present                                           โ”‚
โ”‚  โ€ข User feedback appropriate                                        โ”‚
โ”‚  โ€ข Security considerations                                          โ”‚
โ”‚  โ€ข Performance implications                                         โ”‚
โ”‚                                                                     โ”‚
โ”‚  STEP 4: VERIFY VERSION COMPATIBILITY                               โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                               โ”‚
โ”‚  โ€ข v14/v15/v16 specific features                                    โ”‚
โ”‚  โ€ข Deprecated patterns                                              โ”‚
โ”‚  โ€ข Version-specific behaviors                                       โ”‚
โ”‚                                                                     โ”‚
โ”‚  STEP 5: GENERATE VALIDATION REPORT                                 โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                 โ”‚
โ”‚  โ€ข Critical errors (must fix)                                       โ”‚
โ”‚  โ€ข Warnings (should fix)                                            โ”‚
โ”‚  โ€ข Suggestions (nice to have)                                       โ”‚
โ”‚  โ€ข Corrected code (if errors found)                                 โ”‚
โ”‚                                                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ†’ See references/workflow.md for detailed validation steps.

Critical Checks by Code Type

Server Script Checks

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ โš ๏ธ  SERVER SCRIPT CRITICAL CHECKS                                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Import statements                                           โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                         โ”‚
โ”‚ โŒ import json                    โ†’ Use frappe.parse_json()         โ”‚
โ”‚ โŒ from frappe.utils import X     โ†’ Use frappe.utils.X()            โ”‚
โ”‚ โŒ import requests                โ†’ IMPOSSIBLE in Server Script     โ”‚
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Undefined variables                                         โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                        โ”‚
โ”‚ โŒ self.field                     โ†’ Use doc.field                   โ”‚
โ”‚ โŒ document.field                 โ†’ Use doc.field                   โ”‚
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Wrong event handling                                        โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                     โ”‚
โ”‚ โŒ try/except for validation      โ†’ Just frappe.throw()             โ”‚
โ”‚                                                                     โ”‚
โ”‚ [ERROR] Event name mismatch                                         โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                         โ”‚
โ”‚ โŒ Event "Before Save" code in "After Save" script                  โ”‚
โ”‚                                                                     โ”‚
โ”‚ [WARNING] Missing validation                                        โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                     โ”‚
โ”‚ โš ๏ธ  No null/empty checks before operations                          โ”‚
โ”‚                                                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Client Script Checks

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ CLIENT SCRIPT CRITICAL CHECKS                                       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Wrong API usage                                             โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                           โ”‚
โ”‚ โŒ frappe.db.get_value()          โ†’ Server-side only!               โ”‚
โ”‚ โŒ frappe.get_doc()               โ†’ Server-side only!               โ”‚
โ”‚ โœ“  frappe.call() for server data                                    โ”‚
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Missing async handling                                      โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                      โ”‚
โ”‚ โŒ let result = frappe.call()     โ†’ Returns undefined               โ”‚
โ”‚ โœ“  frappe.call({callback: fn})   โ†’ Use callback                     โ”‚
โ”‚ โœ“  await frappe.call({async:false}) โ†’ Or async/await               โ”‚
โ”‚                                                                     โ”‚
โ”‚ [ERROR] Field refresh issues                                        โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                        โ”‚
โ”‚ โŒ frm.set_value() without refresh                                  โ”‚
โ”‚ โœ“  frm.set_value() then frm.refresh_field()                        โ”‚
โ”‚                                                                     โ”‚
โ”‚ [WARNING] Form state checks                                         โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                         โ”‚
โ”‚ โš ๏ธ  Not checking frm.doc.__islocal for new docs                     โ”‚
โ”‚ โš ๏ธ  Not checking frm.doc.docstatus for submitted docs               โ”‚
โ”‚                                                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Controller Checks

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ CONTROLLER CRITICAL CHECKS                                          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Wrong lifecycle usage                                       โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                       โ”‚
โ”‚ โŒ Modifying self.field in on_update โ†’ Changes NOT saved!           โ”‚
โ”‚ โœ“  Use frappe.db.set_value() in on_update                          โ”‚
โ”‚                                                                     โ”‚
โ”‚ [FATAL] Missing super() call                                        โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                        โ”‚
โ”‚ โŒ def validate(self): pass        โ†’ Breaks parent validation       โ”‚
โ”‚ โœ“  def validate(self): super().validate()                          โ”‚
โ”‚                                                                     โ”‚
โ”‚ [ERROR] Transaction assumptions                                     โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                     โ”‚
โ”‚ โŒ Assuming rollback on error in on_update                          โ”‚
โ”‚    (only validate and before_* roll back on error)                 โ”‚
โ”‚                                                                     โ”‚
โ”‚ [ERROR] Circular save                                               โ”‚
โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                              โ”‚
โ”‚ โŒ self.save() inside lifecycle hooks                               โ”‚
โ”‚ โŒ doc.save() for same document in hooks                            โ”‚
โ”‚                                                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ†’ See references/checklists.md for complete checklists.

Validation Report Format

## Code Validation Report

### Code Type: [Server Script / Client Script / Controller / etc.]
### Target DocType: [DocType name]
### Event/Trigger: [Event name]

---

### ๐Ÿ”ด CRITICAL ERRORS (Must Fix)

| Line | Issue | Fix |
|------|-------|-----|
| 3 | Import statement in Server Script | Use frappe.utils.X() directly |

### ๐ŸŸก WARNINGS (Should Fix)

| Line | Issue | Recommendation |
|------|-------|----------------|
| 12 | No null check before .lower() | Add: if value: value.lower() |

### ๐Ÿ”ต SUGGESTIONS (Nice to Have)

| Line | Suggestion |
|------|------------|
| 8 | Consider using frappe.db.get_value for single field |

---

### Corrected Code

```python
# [Corrected version with all critical errors fixed]

Version Compatibility

Version Status
v14 โœ… Compatible
v15 โœ… Compatible
v16 โœ… Compatible

## Universal Validation Rules

These apply to ALL code types:

### Security Checks

| Check | Severity | Description |
|-------|----------|-------------|
| SQL Injection | CRITICAL | Raw user input in SQL queries |
| Permission bypass | CRITICAL | Missing permission checks before operations |
| XSS vulnerability | HIGH | Unescaped user input in HTML |
| Sensitive data exposure | HIGH | Logging passwords/tokens |

### Error Handling Checks

| Check | Severity | Description |
|-------|----------|-------------|
| Silent failures | HIGH | Catching exceptions without handling |
| Missing user feedback | MEDIUM | Errors not communicated to user |
| Generic error messages | LOW | "An error occurred" without details |

### Performance Checks

| Check | Severity | Description |
|-------|----------|-------------|
| Query in loop | HIGH | frappe.db.* inside for loop |
| Unbounded query | MEDIUM | SELECT without LIMIT |
| Unnecessary get_doc | LOW | get_doc when get_value suffices |

โ†’ See [references/examples.md](references/examples.md) for validation examples.

## Version-Specific Validations

### v16 Features (Fail on v14/v15)

```python
# These ONLY work on v16+
extend_doctype_class = {}  # hooks.py - v16 only
naming_rule = "UUID"       # DocType - v16 only
pdf_renderer = "chrome"    # Print Format - v16 only

Deprecated Patterns (Warn)

# DEPRECATED - still works but should update
frappe.bean()              # Use frappe.get_doc()
frappe.msgprint(raise_exception=True)  # Use frappe.throw()
job_name parameter         # Use job_id (v15+)

Version-Specific Behaviors

Behavior v14 v15/v16
Scheduler tick 240s 60s
Background job dedup job_name job_id

Quick Validation Commands

Server Script Quick Check

  1. โŒ Any import statements? โ†’ FATAL
  2. โŒ Any self. references? โ†’ FATAL (use doc.)
  3. โŒ Any try/except? โ†’ WARNING (usually wrong)
  4. โœ… Uses frappe.throw() for validation errors? โ†’ GOOD
  5. โœ… Uses doc.field for document access? โ†’ GOOD

Client Script Quick Check

  1. โŒ Any frappe.db.* calls? โ†’ FATAL (server-side only)
  2. โŒ Any frappe.get_doc() calls? โ†’ FATAL (server-side only)
  3. โŒ frappe.call() without callback? โ†’ FATAL (async issue)
  4. โœ… Uses frm.doc.field for field access? โ†’ GOOD
  5. โœ… Uses frm.refresh_field() after changes? โ†’ GOOD

Controller Quick Check

  1. โŒ Modifying self.* in on_update? โ†’ ERROR (won't save)
  2. โŒ Missing super().method() calls? โ†’ WARNING
  3. โŒ self.save() in lifecycle hook? โ†’ FATAL (circular)
  4. โœ… Imports at top of file? โ†’ GOOD (controllers allow imports)
  5. โœ… Error handling with try/except? โ†’ GOOD (controllers allow this)

Integration with Other Skills

This validator uses knowledge from:

Skill What It Provides
erpnext-syntax-* Correct syntax patterns
erpnext-impl-* Correct implementation patterns
erpnext-errors-* Error handling patterns
erpnext-database Query patterns and pitfalls
erpnext-permissions Permission check patterns
erpnext-api-patterns API response patterns

Validation Depth Levels

Level Checks Use When
Quick Fatal errors only Initial scan
Standard + Warnings Pre-deployment
Deep + Suggestions + Optimization Production review

Default: Standard level for most validations.