Get the FREE Ultimate OpenClaw Setup Guide →

erpnext-code-validator

npx machina-cli add skill OpenAEC-Foundation/ERPNext_Anthropic_Claude_Development_Skill_Package/erpnext-code-validator --openclaw
Files (1)
SKILL.md
18.9 KB

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

VersionStatus
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

Behaviorv14v15/v16
Scheduler tick240s60s
Background job dedupjob_namejob_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:

SkillWhat It Provides
erpnext-syntax-*Correct syntax patterns
erpnext-impl-*Correct implementation patterns
erpnext-errors-*Error handling patterns
erpnext-databaseQuery patterns and pitfalls
erpnext-permissionsPermission check patterns
erpnext-api-patternsAPI response patterns

Validation Depth Levels

LevelChecksUse When
QuickFatal errors onlyInitial scan
Standard+ WarningsPre-deployment
Deep+ Suggestions + OptimizationProduction review

Default: Standard level for most validations.

Source

git clone https://github.com/OpenAEC-Foundation/ERPNext_Anthropic_Claude_Development_Skill_Package/blob/main/skills/source/agents/erpnext-code-validator/SKILL.mdView on GitHub

Overview

An intelligent agent that validates ERPNext/Frappe code against established patterns, common pitfalls, and version compatibility requirements. It helps catch errors before deployment, improving code quality and reducing production issues.

How This Skill Works

The agent first identifies the code type (Client Script JavaScript, Server Script Python sandbox, Controller Python full, hooks.py, Jinja template, or whitelisted method). It then runs type-specific checks, followed by universal rules on error handling, security, and performance, surfacing actionable fixes.

When to Use It

  • Code has been generated and needs review
  • Code is causing errors or not behaving as expected
  • Pre-deployment validation for production readiness
  • Code review focused on best practices and maintainability
  • Review config and integration code (hooks.py, controllers) for compatibility

Quick Start

  1. Step 1: Identify the code type (Client Script, Server Script, Controller, hooks.py, Jinja, or whitelisted method)
  2. Step 2: Run the appropriate type-specific checks and collect findings
  3. Step 3: Review universal rules and apply fixes before deployment

Best Practices

  • Follow the type-specific checklists for Client Script, Server Script, or other code types
  • Verify syntax patterns and correct API usage for ERPNext/Frappe
  • Ensure robust error handling and clear, user-facing feedback
  • Assess security implications and safe data handling
  • Consider performance impact and confirm version compatibility

Example Use Cases

  • Review a Client Script that calls ERPNext APIs before saving
  • Validate a Server Script (Python) for syntax errors and security issues
  • Audit hooks.py to ensure correct event hooks and wiring
  • Validate a Jinja template snippet used in a report to prevent rendering errors
  • Inspect a Python controller for brittle imports or unresolved references

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers