Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问许可证需确认审计通过

erpnext-errors-serverscriptserpnext 错误服务器脚本

Agent Skill

erpnext-errors-serverscripts 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

1,035

周安装

44

GitHub Stars

87

下载量

363
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:erpnext-errors-serverscripts(erpnext 错误服务器脚本)
来源仓库:https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package
仓库路径:skills/erpnext-errors-serverscripts
安装命令:
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-errors-serverscripts
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-errors-serverscripts

简介

说明服务器脚本受限环境下的错误处理方式,禁用 try/except 和 raise 语句。

  • 适用于 Codex、Claude、Cursor、Gemini CLI 中编写符合沙箱安全规范的后台任务。
  • 推荐使用 frappe.throw() 替代 raise,并借助预加载命名空间实现日志记录。
  • 安装前务必确认运行环境限制,防止因语法违规导致脚本执行失败。
  • erpnext-errors-serverscripts 属于开发类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

ERPNext Server Scripts - Error Handling

This skill covers error handling patterns for Server Scripts. For syntax, see erpnext-syntax-serverscripts. For implementation workflows, see erpnext-impl-serverscripts.

Version: v14/v15/v16 compatible


CRITICAL: Sandbox Limitations for Error Handling

┌─────────────────────────────────────────────────────────────────────┐
│ ⚠️  SANDBOX RESTRICTIONS AFFECT ERROR HANDLING                      │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ ❌ NO try/except blocks (blocked in RestrictedPython)               │
│ ❌ NO raise statements (use frappe.throw instead)                   │
│ ❌ NO import traceback                                              │
│                                                                     │
│ ✅ frappe.throw() - Stop execution, show error                      │
│ ✅ frappe.log_error() - Log to Error Log doctype                    │
│ ✅ frappe.msgprint() - Show message, continue execution             │
│ ✅ Conditional checks before operations                             │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Main Decision: How to Handle the Error?

┌─────────────────────────────────────────────────────────────────────────┐
│ WHAT TYPE OF ERROR ARE YOU HANDLING?                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│ ► Validation error (must stop save/submit)?                             │
│   └─► frappe.throw() with clear message                                 │
│                                                                         │
│ ► Warning (inform user, allow continue)?                                │
│   └─► frappe.msgprint() with indicator                                  │
│                                                                         │
│ ► Log error for debugging (no user impact)?                             │
│   └─► frappe.log_error()                                                │
│                                                                         │
│ ► API error response (HTTP error)?                                      │
│   └─► frappe.throw() with exc parameter OR set response                 │
│                                                                         │
│ ► Scheduler task error?                                                 │
│   └─► frappe.log_error() + continue processing other items              │
│                                                                         │
│ ► Prevent operation but not with error dialog?                          │
│   └─► Return early + frappe.msgprint()                                  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Error Methods Reference

Quick Reference

MethodStops Execution?User Sees?Logged?Use For
frappe.throw()✅ YESDialogError LogValidation errors
frappe.msgprint()❌ NODialogNoWarnings
frappe.log_error()❌ NONoError LogDebug/audit
frappe.publish_realtime()❌ NOToastNoBackground updates

frappe.throw() - Stop Execution

# Basic throw - stops execution, rolls back transaction
frappe.throw("Customer is required")

# With title
frappe.throw("Amount cannot be negative", title="Validation Error")

# With exception type (for API scripts)
frappe.throw("Not authorized", exc=frappe.PermissionError)
frappe.throw("Record not found", exc=frappe.DoesNotExistError)

# With formatted message
frappe.throw(
    f"Credit limit exceeded. Limit: {credit_limit}, Requested: {amount}",
    title="Credit Check Failed"
)

Exception Types for API Scripts:

ExceptionHTTP CodeUse For
frappe.ValidationError417Validation failures
frappe.PermissionError403Access denied
frappe.DoesNotExistError404Record not found
frappe.AuthenticationError401Not logged in
frappe.OutgoingEmailError500Email send failed

frappe.log_error() - Silent Logging

# Basic error log
frappe.log_error("Something went wrong", "My Script Error")

# With context data
frappe.log_error(
    f"Failed to process invoice {doc.name}: {error_detail}",
    "Invoice Processing Error"
)

# Log current exception (in controllers, not sandbox)
frappe.log_error(frappe.get_traceback(), "Unexpected Error")

frappe.msgprint() - Warning Without Stopping

# Simple warning
frappe.msgprint("Stock is running low", indicator="orange")

# With title
frappe.msgprint(
    "This customer has pending payments",
    title="Warning",
    indicator="yellow"
)

# Alert style (top of page)
frappe.msgprint(
    "Document will be processed in background",
    alert=True
)

Error Handling Patterns by Script Type

Pattern 1: Document Event - Validation

# Type: Document Event
# Event: Before Save

# Collect all errors, show together
errors = []

if not doc.customer:
    errors.append("Customer is required")

if doc.grand_total <= 0:
    errors.append("Total must be greater than zero")

if not doc.items:
    errors.append("At least one item is required")
else:
    for idx, item in enumerate(doc.items, 1):
        if not item.item_code:
            errors.append(f"Row {idx}: Item Code is required")
        if (item.qty or 0) <= 0:
            errors.append(f"Row {idx}: Quantity must be positive")

# Throw all errors at once
if errors:
    frappe.throw("<br>".join(errors), title="Validation Errors")

Pattern 2: Document Event - Conditional Warning

# Type: Document Event
# Event: Before Save

# Warning: doesn't stop save
credit_limit = frappe.db.get_value("Customer", doc.customer, "credit_limit") or 0

if credit_limit > 0 and doc.grand_total > credit_limit:
    frappe.msgprint(
        f"Order total ({doc.grand_total}) exceeds credit limit ({credit_limit})",
        title="Credit Warning",
        indicator="orange"
    )

Pattern 3: Document Event - Safe Database Lookup

# Type: Document Event
# Event: Before Save

# Always validate before database lookup
if doc.customer:
    customer_data = frappe.db.get_value(
        "Customer",
        doc.customer,
        ["credit_limit", "disabled", "territory"],
        as_dict=True
    )

    # Check if customer exists
    if not customer_data:
        frappe.throw(f"Customer {doc.customer} not found")

    # Check if disabled
    if customer_data.disabled:
        frappe.throw(f"Customer {doc.customer} is disabled")

    # Use the data
    doc.territory = customer_data.territory

Pattern 4: API Script - Error Responses

# Type: API
# Method: get_customer_info

customer = frappe.form_dict.get("customer")

# Validate required parameter
if not customer:
    frappe.throw("Parameter 'customer' is required", exc=frappe.ValidationError)

# Check existence
if not frappe.db.exists("Customer", customer):
    frappe.throw(f"Customer '{customer}' not found", exc=frappe.DoesNotExistError)

# Check permission
if not frappe.has_permission("Customer", "read", customer):
    frappe.throw("You don't have permission to view this customer", exc=frappe.PermissionError)

# Success response
frappe.response["message"] = {
    "customer": customer,
    "credit_limit": frappe.db.get_value("Customer", customer, "credit_limit")
}

Pattern 5: Scheduler - Batch Processing with Error Isolation

# Type: Scheduler Event
# Cron: 0 9 * * * (daily at 9:00)

processed = 0
errors = []

invoices = frappe.get_all(
    "Sales Invoice",
    filters={"status": "Unpaid", "docstatus": 1},
    fields=["name", "customer"],
    limit=100  # ALWAYS limit in scheduler
)

for inv in invoices:
    # Isolate errors per item - don't let one failure stop all
    if not frappe.db.exists("Customer", inv.customer):
        errors.append(f"{inv.name}: Customer not found")
        continue

    # Safe processing
    result = process_invoice(inv.name)
    if result.get("success"):
        processed += 1
    else:
        errors.append(f"{inv.name}: {result.get('error', 'Unknown error')}")

# Log summary
if errors:
    frappe.log_error(
        f"Processed: {processed}, Errors: {len(errors)}\n\n" + "\n".join(errors),
        "Invoice Processing Summary"
    )

# REQUIRED: commit in scheduler
frappe.db.commit()

def process_invoice(invoice_name):
    """Helper function with error handling"""
    # Validate invoice exists
    if not frappe.db.exists("Sales Invoice", invoice_name):
        return {"success": False, "error": "Invoice not found"}

    # Process logic here
    return {"success": True}

Pattern 6: Permission Query - Safe Fallback

# Type: Permission Query
# DocType: Sales Invoice

# Safe role check
user_roles = frappe.get_roles(user) or []

if "System Manager" in user_roles:
    conditions = ""  # Full access
elif "Sales Manager" in user_roles:
    # Manager sees team's invoices
    team = frappe.db.get_value("User", user, "department")
    if team:
        conditions = f"`tabSales Invoice`.department = {frappe.db.escape(team)}"
    else:
        conditions = f"`tabSales Invoice`.owner = {frappe.db.escape(user)}"
elif "Sales User" in user_roles:
    # User sees only own invoices
    conditions = f"`tabSales Invoice`.owner = {frappe.db.escape(user)}"
else:
    # No access - return impossible condition
    conditions = "1=0"
See: references/patterns.md for more error handling patterns.

Transaction Behavior

Automatic Rollback on frappe.throw()

# Type: Document Event - Before Save

# All changes roll back if throw is called
doc.status = "Processing"  # This change...
frappe.db.set_value("Counter", "main", "count", 100)  # ...and this...

if some_condition_fails:
    frappe.throw("Validation failed")  # ...are ALL rolled back

Manual Commit in Scheduler

# Type: Scheduler Event

# Changes are NOT auto-committed in scheduler
for item in items:
    frappe.db.set_value("Item", item.name, "last_sync", frappe.utils.now())

# REQUIRED: Explicit commit
frappe.db.commit()

Partial Commit Pattern (Scheduler)

# Type: Scheduler Event
# Process in batches with intermediate commits

BATCH_SIZE = 50
items = frappe.get_all("Item", filters={"sync_pending": 1}, limit=500)

for i in range(0, len(items), BATCH_SIZE):
    batch = items[i:i + BATCH_SIZE]

    for item in batch:
        frappe.db.set_value("Item", item.name, "sync_pending", 0)

    # Commit after each batch - partial progress saved
    frappe.db.commit()

Critical Rules

✅ ALWAYS

  1. Validate inputs before database operations - Check existence before get_doc
  2. Use frappe.db.escape() for user input in SQL - Prevent SQL injection
  3. Add limit to queries in Scheduler scripts - Prevent memory issues
  4. Call frappe.db.commit() in Scheduler scripts - Changes aren't auto-saved
  5. Collect multiple errors before throwing - Better user experience
  6. Log errors in Scheduler scripts - No user to see the error

❌ NEVER

  1. Don't use try/except in Server Scripts - Blocked by sandbox
  2. Don't use raise statement - Use frappe.throw() instead
  3. Don't call doc.save() in Before Save event - Framework handles it
  4. Don't assume database values exist - Always check first
  5. Don't ignore empty results - Handle gracefully

Quick Reference: Error Message Quality

# ❌ BAD - Technical, not actionable
frappe.throw("KeyError: customer")
frappe.throw("NoneType has no attribute 'name'")
frappe.throw("Query failed")

# ✅ GOOD - Clear, actionable
frappe.throw("Please select a customer before saving")
frappe.throw(f"Customer '{doc.customer}' not found. Please verify the customer exists.")
frappe.throw("Could not calculate totals. Please ensure all items have valid quantities.")

Reference Files

FileContents
references/patterns.mdComplete error handling patterns
references/examples.mdFull working examples
references/anti-patterns.mdCommon mistakes to avoid

See Also

  • erpnext-syntax-serverscripts - Server Script syntax
  • erpnext-impl-serverscripts - Implementation workflows
  • erpnext-errors-clientscripts - Client-side error handling
  • erpnext-database - Database operations

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

33.35%
按下载量换算121

Claude

32.24%
按下载量换算117

Cursor

18.76%
按下载量换算68

Gemini CLI

9.33%
按下载量换算34

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills