Token导航 LogoToken导航

Agent Skill · 开发

erpnext-errors-clientscripts(erpnext 错误客户端脚本)

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

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

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

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

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

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

这个 Skill 是做什么的

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

记录客户端脚本中的错误处理模式,帮助 Agent 沉淀问题修正与最佳实践。适用于 Codex、Claude、Cursor、Gemini CLI 中持续优化表单验证和用户交互逻辑。可结合原始 README 核验具体用法,如 frappe.throw() 的使用场景和事件触发时机。

安装前需确认是否涉及文件读写或命令执行,并评估对生产环境的影响。erpnext-errors-clientscripts 属于开发类 Skill,可作为该场景下的辅助能力补充。

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

上手步骤

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-clientscripts 怎么安装?

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

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

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

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

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

erpnext-errors-clientscripts 是免费的吗?

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

erpnext-errors-clientscripts 用的人多吗?

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

erpnext-errors-clientscripts 安全吗?

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

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

值得选的地方

  • 同时适配 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-clientscripts

erpnext 错误客户端脚本 · 本页

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

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

SKILL.md 原文

ERPNext Client Scripts - Error Handling

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

Version: v14/v15/v16 compatible


Main Decision: How to Handle the Error?

┌─────────────────────────────────────────────────────────────────────────┐
│ WHAT TYPE OF ERROR ARE YOU HANDLING?                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│ ► Validation error (must prevent save)?                                 │
│   └─► frappe.throw() in validate event                                  │
│                                                                         │
│ ► Warning (inform user, allow continue)?                                │
│   └─► frappe.msgprint() with indicator                                  │
│                                                                         │
│ ► Server call might fail?                                               │
│   └─► try/catch with async/await OR callback error handling             │
│                                                                         │
│ ► Field value invalid (not blocking)?                                   │
│   └─► frm.set_intro() or field description                              │
│                                                                         │
│ ► Need to debug/trace?                                                  │
│   └─► console.log/warn/error + frappe.show_alert for dev                │
│                                                                         │
│ ► Unexpected error in any code?                                         │
│   └─► Wrap in try/catch, log error, show user-friendly message          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Error Feedback Methods

Quick Reference

MethodBlocks Save?User ActionUse For
frappe.throw()✅ YESMust dismissValidation errors
frappe.msgprint()❌ NOMust dismissImportant info/warnings
frappe.show_alert()❌ NOAuto-dismissSuccess/info feedback
frm.set_intro()❌ NONoneForm-level warnings
frm.dashboard.set_headline()❌ NONoneStatus indicators
console.error()❌ NONoneDebugging only

frappe.throw() - Blocking Error

// Basic throw - stops execution, prevents save
frappe.throw(__('Customer is required'));

// With title
frappe.throw({
    title: __('Validation Error'),
    message: __('Amount cannot be negative')
});

// With indicator color
frappe.throw({
    message: __('Credit limit exceeded'),
    indicator: 'red'
});

CRITICAL: Only use frappe.throw() in validate event to prevent save. Using it elsewhere stops script execution but doesn't prevent form actions.

frappe.msgprint() - Non-Blocking Alert

// Simple message
frappe.msgprint(__('Document will be processed'));

// With title and indicator
frappe.msgprint({
    title: __('Warning'),
    message: __('Stock is running low'),
    indicator: 'orange'
});

// With primary action button
frappe.msgprint({
    title: __('Confirm Action'),
    message: __('This will archive 50 records. Continue?'),
    primary_action: {
        label: __('Yes, Archive'),
        action: () => {
            // perform action
            frappe.hide_msgprint();
        }
    }
});

frappe.show_alert() - Toast Notification

// Success (green, auto-dismiss)
frappe.show_alert({
    message: __('Saved successfully'),
    indicator: 'green'
}, 3);  // 3 seconds

// Warning (orange)
frappe.show_alert({
    message: __('Some items are out of stock'),
    indicator: 'orange'
}, 5);

// Error (red)
frappe.show_alert({
    message: __('Failed to fetch data'),
    indicator: 'red'
}, 5);

Error Handling Patterns

Pattern 1: Synchronous Validation

frappe.ui.form.on('Sales Order', {
    validate(frm) {
        // Multiple validations - collect errors
        let errors = [];

        if (!frm.doc.customer) {
            errors.push(__('Customer is required'));
        }

        if (frm.doc.grand_total <= 0) {
            errors.push(__('Total must be greater than zero'));
        }

        if (!frm.doc.items || frm.doc.items.length === 0) {
            errors.push(__('At least one item is required'));
        }

        // Throw all errors at once
        if (errors.length > 0) {
            frappe.throw({
                title: __('Validation Errors'),
                message: errors.join('<br>')
            });
        }
    }
});

Pattern 2: Async Server Call with Error Handling

frappe.ui.form.on('Sales Order', {
    async customer(frm) {
        if (!frm.doc.customer) return;

        try {
            let r = await frappe.call({
                method: 'myapp.api.get_customer_details',
                args: { customer: frm.doc.customer }
            });

            if (r.message) {
                frm.set_value('credit_limit', r.message.credit_limit);
            }
        } catch (error) {
            console.error('Failed to fetch customer:', error);
            frappe.show_alert({
                message: __('Could not load customer details'),
                indicator: 'red'
            }, 5);
            // Don't throw - allow user to continue
        }
    }
});

Pattern 3: Async Validation with Server Check

frappe.ui.form.on('Sales Order', {
    async validate(frm) {
        // Server-side validation
        try {
            let r = await frappe.call({
                method: 'myapp.api.validate_order',
                args: {
                    customer: frm.doc.customer,
                    total: frm.doc.grand_total
                }
            });

            if (r.message && !r.message.valid) {
                frappe.throw({
                    title: __('Validation Failed'),
                    message: r.message.error
                });
            }
        } catch (error) {
            // Server error - decide: block or allow?
            console.error('Validation call failed:', error);

            // Option 1: Block save on server error (safer)
            frappe.throw(__('Could not validate. Please try again.'));

            // Option 2: Allow save with warning (use with caution)
            // frappe.show_alert({
            //     message: __('Validation skipped due to server error'),
            //     indicator: 'orange'
            // }, 5);
        }
    }
});

Pattern 4: frappe.call Callback Error Handling

// When not using async/await
frappe.call({
    method: 'myapp.api.process_data',
    args: { doc_name: frm.doc.name },
    freeze: true,
    freeze_message: __('Processing...'),
    callback: (r) => {
        if (r.message) {
            frappe.show_alert({
                message: __('Processing complete'),
                indicator: 'green'
            });
            frm.reload_doc();
        }
    },
    error: (r) => {
        // Server returned error (4xx, 5xx)
        console.error('API Error:', r);
        frappe.msgprint({
            title: __('Error'),
            message: __('Processing failed. Please try again.'),
            indicator: 'red'
        });
    }
});

Pattern 5: Child Table Validation

frappe.ui.form.on('Sales Invoice', {
    validate(frm) {
        let errors = [];

        (frm.doc.items || []).forEach((row, idx) => {
            if (!row.item_code) {
                errors.push(__('Row {0}: Item is required', [idx + 1]));
            }
            if (row.qty <= 0) {
                errors.push(__('Row {0}: Quantity must be positive', [idx + 1]));
            }
            if (row.rate < 0) {
                errors.push(__('Row {0}: Rate cannot be negative', [idx + 1]));
            }
        });

        if (errors.length > 0) {
            frappe.throw({
                title: __('Item Errors'),
                message: errors.join('<br>')
            });
        }
    }
});

Pattern 6: Graceful Degradation

frappe.ui.form.on('Sales Order', {
    async refresh(frm) {
        // Try to load extra data, but don't fail if unavailable
        try {
            let stock = await frappe.call({
                method: 'myapp.api.get_stock_summary',
                args: { items: frm.doc.items.map(r => r.item_code) }
            });

            if (stock.message) {
                render_stock_dashboard(frm, stock.message);
            }
        } catch (error) {
            // Log but don't disturb user
            console.warn('Stock dashboard unavailable:', error);
            // Optionally show subtle indicator
            frm.dashboard.set_headline(
                __('Stock info unavailable'),
                'orange'
            );
        }
    }
});
See: references/patterns.md for more error handling patterns.

Debugging Techniques

Console Logging

// Development debugging
frappe.ui.form.on('Sales Order', {
    customer(frm) {
        console.log('Customer changed:', frm.doc.customer);
        console.log('Full doc:', JSON.parse(JSON.stringify(frm.doc)));

        // Trace child table
        console.table(frm.doc.items);
    }
});

Conditional Debugging

// Only log in development
const DEBUG = frappe.boot.developer_mode;

function debugLog(...args) {
    if (DEBUG) {
        console.log('[MyApp]', ...args);
    }
}

frappe.ui.form.on('Sales Order', {
    validate(frm) {
        debugLog('Validating:', frm.doc.name);
        // validation logic
    }
});

Error Stack Traces

try {
    riskyOperation();
} catch (error) {
    console.error('Error details:', {
        message: error.message,
        stack: error.stack,
        doc: frm.doc.name
    });

    // User-friendly message (no technical details)
    frappe.msgprint({
        title: __('Error'),
        message: __('An unexpected error occurred. Please contact support.'),
        indicator: 'red'
    });
}

Critical Rules

✅ ALWAYS

  1. Wrap async calls in try/catch - Uncaught Promise rejections crash silently
  2. Use __() for error messages - All user-facing text must be translatable
  3. Log errors to console - Helps debugging without exposing to users
  4. Collect multiple validation errors - Don't throw on first error
  5. Provide actionable error messages - Tell user how to fix it

❌ NEVER

  1. Don't expose technical errors to users - Catch and translate
  2. Don't use frappe.throw() outside validate - It stops execution but doesn't prevent save
  3. Don't ignore server call failures - Always handle error callback
  4. Don't use alert() or confirm() - Use frappe methods instead
  5. Don't leave console.log in production - Use conditional debugging

Quick Reference: Error Message Quality

// ❌ BAD - Technical, not actionable
frappe.throw('NullPointerException in line 42');
frappe.throw('Query failed');
frappe.throw('Error');

// ✅ GOOD - Clear, actionable
frappe.throw(__('Please select a customer before adding items'));
frappe.throw(__('Amount {0} exceeds credit limit of {1}', [amount, limit]));
frappe.throw(__('Could not save. Please check your internet connection and try again.'));

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-clientscripts - Client Script syntax
  • erpnext-impl-clientscripts - Implementation workflows
  • erpnext-errors-serverscripts - Server-side error handling

平台分布

Codex

36.86%
按下载量换算133

Claude

28.89%
按下载量换算104

Cursor

18.95%
按下载量换算68

Gemini CLI

10.43%
按下载量换算38

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

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

继续浏览同类 Skills