Token导航 LogoToken导航

Agent Skill · 开发

erpnext-errors-database(erpnext 错误数据库)

用于辅助数据库表结构、查询语句、迁移脚本和数据维护任务。它适合让 Agent 分析 schema、编写 SQL、排查查询问题、整理索引或生成迁移建议。使用时需要明确数据库类型、连接环境和目标表,区分只读分析与写入变更;涉及删除、更新、迁移和批量导入时,应优先 dry-run、备份或事务保护,避免误操作。

erpnext-errors-database 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 12,747。

总安装 1,148周安装 46GitHub Stars 87下载 372核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

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

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

命令行安装

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

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

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

辅助数据库操作中的错误识别与处理,涵盖唯一约束、链接依赖等常见问题。适合在 Codex、Claude、Cursor、Gemini CLI 中排查查询性能或迁移脚本风险。使用时需明确数据库类型和连接环境,区分只读分析与写入变更操作。涉及删除或批量更新时,应优先 dry-run 或启用事务保护以防数据丢失。

erpnext-errors-database 属于开发类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/erpnext-errors-database

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_de…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

erpnext-errors-database 怎么安装?

在终端执行 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

erpnext-errors-database 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

erpnext-errors-database 需要什么权限?

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

erpnext-errors-database 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

erpnext-errors-database 用的人多吗?

公开数据是累计安装 1,148 次,近一周安装 46 次,下载 372 次,GitHub 87 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

erpnext-errors-database 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
erpnext-errors-database

erpnext 错误数据库 · 本页

1,14887需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

ERPNext Database - Error Handling

This skill covers error handling patterns for database operations. For syntax, see erpnext-database.

Version: v14/v15/v16 compatible


Database Exception Types

┌─────────────────────────────────────────────────────────────────────┐
│ FRAPPE DATABASE EXCEPTIONS                                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ frappe.DoesNotExistError                                            │
│   └─► Document not found (get_doc, get_value with strict)           │
│                                                                     │
│ frappe.DuplicateEntryError                                          │
│   └─► Unique constraint violation (insert, rename)                  │
│                                                                     │
│ frappe.LinkExistsError                                              │
│   └─► Cannot delete - linked documents exist                        │
│                                                                     │
│ frappe.ValidationError                                              │
│   └─► General validation failure                                    │
│                                                                     │
│ frappe.TimestampMismatchError                                       │
│   └─► Concurrent edit detected (modified since load)                │
│                                                                     │
│ frappe.db.InternalError                                             │
│   └─► Database-level error (deadlock, connection lost)              │
│                                                                     │
│ frappe.QueryTimeoutError (v15+)                                     │
│   └─► Query exceeded timeout limit                                  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Main Decision: Error Handling by Operation

┌─────────────────────────────────────────────────────────────────────────┐
│ WHAT DATABASE OPERATION?                                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│ ► frappe.get_doc() / frappe.get_cached_doc()                            │
│   └─► Can raise DoesNotExistError                                       │
│   └─► Check with frappe.db.exists() first OR catch exception            │
│                                                                         │
│ ► doc.insert() / frappe.new_doc().insert()                              │
│   └─► Can raise DuplicateEntryError (unique constraints)                │
│   └─► Can raise ValidationError (mandatory fields, custom validation)   │
│                                                                         │
│ ► doc.save()                                                            │
│   └─► Can raise ValidationError                                         │
│   └─► Can raise TimestampMismatchError (concurrent edit)                │
│                                                                         │
│ ► doc.delete() / frappe.delete_doc()                                    │
│   └─► Can raise LinkExistsError (linked documents)                      │
│   └─► Use force=True to ignore links (careful!)                         │
│                                                                         │
│ ► frappe.db.sql() / frappe.qb                                           │
│   └─► Can raise InternalError (syntax, deadlock, connection)            │
│   └─► Always use parameterized queries                                  │
│                                                                         │
│ ► frappe.db.set_value() / doc.db_set()                                  │
│   └─► Silently fails if record doesn't exist                            │
│   └─► No validation triggered                                           │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Error Handling Patterns

Pattern 1: Safe Document Fetch

# Option A: Check first (preferred for expected missing docs)
if frappe.db.exists("Customer", customer_name):
    customer = frappe.get_doc("Customer", customer_name)
else:
    frappe.throw(_("Customer '{0}' not found").format(customer_name))

# Option B: Try/except (preferred when doc usually exists)
try:
    customer = frappe.get_doc("Customer", customer_name)
except frappe.DoesNotExistError:
    frappe.throw(_("Customer '{0}' not found").format(customer_name))

# Option C: Get with default (for optional lookups)
customer = frappe.db.get_value("Customer", customer_name, "*", as_dict=True)
if not customer:
    # Handle missing - no error raised
    customer = {"customer_name": "Unknown", "credit_limit": 0}

Pattern 2: Safe Document Insert

def create_customer(data):
    """Create customer with duplicate handling."""
    try:
        doc = frappe.get_doc({
            "doctype": "Customer",
            "customer_name": data.get("name"),
            "customer_type": data.get("type", "Company")
        })
        doc.insert()
        return {"success": True, "name": doc.name}

    except frappe.DuplicateEntryError:
        # Already exists - return existing
        existing = frappe.db.get_value("Customer", {"customer_name": data.get("name")})
        return {"success": True, "name": existing, "existing": True}

    except frappe.ValidationError as e:
        return {"success": False, "error": str(e)}

Pattern 3: Safe Document Delete

def delete_customer(customer_name):
    """Delete customer with link handling."""
    if not frappe.db.exists("Customer", customer_name):
        frappe.throw(_("Customer '{0}' not found").format(customer_name))

    try:
        frappe.delete_doc("Customer", customer_name)
        return {"success": True}

    except frappe.LinkExistsError as e:
        # Get linked documents for user info
        linked = get_linked_documents("Customer", customer_name)
        frappe.throw(
            _("Cannot delete customer. Linked documents exist:<br>{0}").format(
                "<br>".join([f"• {l['doctype']}: {l['name']}" for l in linked[:10]])
            )
        )

Pattern 4: Concurrent Edit Handling

def update_document(doctype, name, updates):
    """Update with concurrent edit detection."""
    try:
        doc = frappe.get_doc(doctype, name)
        doc.update(updates)
        doc.save()
        return {"success": True}

    except frappe.TimestampMismatchError:
        # Document was modified by another user
        frappe.throw(
            _("This document was modified by another user. Please refresh and try again."),
            title=_("Concurrent Edit Detected")
        )
    except frappe.DoesNotExistError:
        frappe.throw(_("Document not found"))

Pattern 5: Batch Operations with Error Isolation

def bulk_update_items(items_data):
    """Bulk update with per-item error handling."""
    results = {"success": [], "failed": []}

    for item_data in items_data:
        item_code = item_data.get("item_code")

        try:
            if not frappe.db.exists("Item", item_code):
                results["failed"].append({
                    "item": item_code,
                    "error": "Item not found"
                })
                continue

            doc = frappe.get_doc("Item", item_code)
            doc.update(item_data)
            doc.save()
            results["success"].append(item_code)

        except frappe.ValidationError as e:
            results["failed"].append({
                "item": item_code,
                "error": str(e)
            })
        except Exception as e:
            frappe.log_error(frappe.get_traceback(), f"Bulk update error: {item_code}")
            results["failed"].append({
                "item": item_code,
                "error": "Unexpected error"
            })

    return results

Pattern 6: Safe SQL Query

def get_sales_report(customer, from_date, to_date):
    """Safe SQL query with error handling."""
    try:
        # ALWAYS use parameterized queries
        result = frappe.db.sql("""
            SELECT
                customer,
                SUM(grand_total) as total,
                COUNT(*) as count
            FROM `tabSales Invoice`
            WHERE customer = %(customer)s
            AND posting_date BETWEEN %(from_date)s AND %(to_date)s
            AND docstatus = 1
            GROUP BY customer
        """, {
            "customer": customer,
            "from_date": from_date,
            "to_date": to_date
        }, as_dict=True)

        return result[0] if result else {"total": 0, "count": 0}

    except frappe.db.InternalError as e:
        frappe.log_error(frappe.get_traceback(), "Sales Report Query Error")
        frappe.throw(_("Database error. Please try again or contact support."))
See: references/patterns.md for more error handling patterns.

Transaction Handling

Automatic Transaction Management

# Frappe wraps each request in a transaction
# On success: auto-commit
# On exception: auto-rollback

def validate(self):
    # All changes are in ONE transaction
    self.calculate_totals()
    frappe.db.set_value("Counter", "main", "count", 100)

    if error_condition:
        frappe.throw("Error")  # EVERYTHING rolls back

Manual Savepoints (Advanced)

def complex_operation():
    """Use savepoints for partial rollback."""
    # Create savepoint
    frappe.db.savepoint("before_risky_op")

    try:
        risky_database_operation()
    except Exception:
        # Rollback only to savepoint
        frappe.db.rollback(save_point="before_risky_op")
        frappe.log_error(frappe.get_traceback(), "Risky Op Failed")
        # Continue with alternative approach
        safe_alternative_operation()

Scheduler/Background Jobs

def background_task():
    """Background jobs need explicit commit."""
    try:
        for record in records:
            process_record(record)

        # REQUIRED in background jobs
        frappe.db.commit()

    except Exception:
        frappe.db.rollback()
        frappe.log_error(frappe.get_traceback(), "Background Task Error")

Critical Rules

✅ ALWAYS

  1. Check existence before get_doc - Or catch DoesNotExistError
  2. Use parameterized SQL queries - Never string formatting
  3. Handle DuplicateEntryError on insert - Unique constraints
  4. Commit in scheduler/background jobs - No auto-commit
  5. Log database errors with context - Include query/doc info
  6. Use db.exists() for existence checks - Not try/except get_doc

❌ NEVER

  1. Don't use string formatting in SQL - SQL injection risk
  2. Don't commit in controller hooks - Breaks transaction
  3. Don't ignore DoesNotExistError silently - Handle or log
  4. Don't assume db.set_value() succeeded - No error on missing doc
  5. Don't catch generic Exception for database ops - Catch specific types

Quick Reference: Exception Handling

# DoesNotExistError - Document not found
try:
    doc = frappe.get_doc("Customer", name)
except frappe.DoesNotExistError:
    frappe.throw(_("Customer not found"))

# DuplicateEntryError - Unique constraint violation
try:
    doc.insert()
except frappe.DuplicateEntryError:
    # Handle duplicate

# LinkExistsError - Cannot delete linked document
try:
    frappe.delete_doc("Customer", name)
except frappe.LinkExistsError:
    frappe.throw(_("Cannot delete - linked documents exist"))

# TimestampMismatchError - Concurrent edit
try:
    doc.save()
except frappe.TimestampMismatchError:
    frappe.throw(_("Document was modified. Please refresh."))

# InternalError - Database-level error
try:
    frappe.db.sql(query)
except frappe.db.InternalError:
    frappe.log_error(frappe.get_traceback(), "Database Error")
    frappe.throw(_("Database error occurred"))

Reference Files

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

See Also

  • erpnext-database - Database operations syntax
  • erpnext-errors-controllers - Controller error handling
  • erpnext-errors-serverscripts - Server Script error handling
  • erpnext-permissions - Permission patterns

平台分布

Codex

35.42%
按下载量换算132

Claude

28.77%
按下载量换算107

Cursor

19.34%
按下载量换算72

Gemini CLI

10.39%
按下载量换算39

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

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

继续浏览同类 Skills