You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use when debugging or preventing errors in Frappe Server Scripts. Prevents ImportError (the #1 error), NameError for restricted builtins, sandbox violations, doc_events not firing, wrong script type selection, SQL injection, permission denied in scheduled scripts, infinite loops, and API scripts not returning JSON. Covers error message mapping table. Keywords: server script error, ImportError, NameError, sandbox,, ImportError in server script, script not running, sandbox error, restricted function. restricted, frappe.throw, doc_events, scheduler, API script, SQL injection.
license
MIT
compatibility
Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16.
Verify type matches: Document Event, API, or Scheduler
doc is not defined
Using doc in API or Scheduler script (no document context)
doc is only available in Document Event scripts
PermissionError in Scheduler
Scheduler runs as Administrator but script accesses restricted resource
Use ignore_permissions=True where appropriate
Changes not saved in Scheduler
Missing frappe.db.commit()
ALWAYS call frappe.db.commit() in Scheduler scripts
API returns empty response
Forgot to set frappe.response["message"]
ALWAYS set frappe.response["message"] = result
Timeout / killed
Infinite loop or processing too many records
ALWAYS add limit to queries, ALWAYS use batch processing
ValidationError: qty is required
doc.save() called in Before Save (recursion)
NEVER call doc.save() in Before Save; just set values
SQL injection via string format
User input in SQL without escaping
ALWAYS use frappe.db.escape() or parameterized queries
The #1 Error: ImportError
Every beginner hits this. The Server Script sandbox blocks ALL imports except json.
# ❌ BLOCKED — These ALL fail with ImportErrorimportjson# Use frappe.parse_json() / frappe.as_json()fromdatetimeimportdatetime# Use frappe.utils.now(), frappe.utils.today()importre# Not available in sandboximportos# Security: blockedimportrequests# Use frappe.make_get_request(), frappe.make_post_request()# ✅ CORRECT — Sandbox equivalentsdata=frappe.parse_json(doc.json_field) # Instead of json.loads()today=frappe.utils.today() # Instead of datetime.date.today()now=frappe.utils.now() # Instead of datetime.now()diff=frappe.utils.date_diff(date1, date2) # Instead of timedeltaresp=frappe.make_get_request("https://api.com") # Instead of requests.get()resp=frappe.make_post_request("https://api.com", data=payload)