← Back to list

erpnext-errors-api
by OpenAEC-Foundation
28 deterministic Claude AI skills for flawless ERPNext/Frappe v14-16 development. Agent Skills standard compliant.
⭐ 1🍴 1📅 Jan 23, 2026
SKILL.md
name: erpnext-errors-api description: "Error handling patterns for ERPNext/Frappe API development (v14/v15/v16). Covers whitelisted method errors, REST API errors, client-side handling, external integrations, and webhooks. Triggers: API error, whitelisted method error, frappe.call error, REST API error, webhook error, external API error, HTTP status codes."
ERPNext API Error Handling
Patterns for handling errors in API development. For syntax details, see erpnext-api-patterns.
Version: v14/v15/v16 compatible
API Error Handling Overview
┌─────────────────────────────────────────────────────────────────────┐
│ API ERROR HANDLING DECISION │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Where is the error occurring? │
│ │
│ Server-side (Python)? │
│ ├── Validation error → frappe.throw() with clear message │
│ ├── Permission error → frappe.throw() + PermissionError │
│ ├── Not found → frappe.throw() + DoesNotExistError │
│ └── Unexpected → Log + generic error to client │
│ │
│ Client-side (JavaScript)? │
│ ├── frappe.call → Use error callback or .catch() │
│ └── frappe.xcall → Use try/catch with async/await │
│ │
│ External integration? │
│ └── requests library → try/except with specific exceptions │
│ │
└─────────────────────────────────────────────────────────────────────┘
HTTP Status Codes Reference
| Code | Meaning | When Frappe Uses |
|---|---|---|
| 200 | Success | Normal response |
| 400 | Bad Request | Validation error |
| 403 | Forbidden | Permission denied |
| 404 | Not Found | Document doesn't exist |
| 417 | Expectation Failed | frappe.throw() called |
| 500 | Server Error | Unhandled exception |
Server-Side Patterns
Basic Whitelisted Method
@frappe.whitelist()
def update_status(docname, status):
# Validate input
if not docname:
frappe.throw(_("Document name is required"), frappe.ValidationError)
if status not in ["Draft", "Submitted", "Cancelled"]:
frappe.throw(_("Invalid status: {0}").format(status))
try:
doc = frappe.get_doc("My DocType", docname)
doc.status = status
doc.save()
return {"success": True, "name": doc.name}
except frappe.DoesNotExistError:
frappe.throw(_("Document {0} not found").format(docname))
except frappe.PermissionError:
frappe.throw(_("Permission denied"), frappe.PermissionError)
Bulk Operation with Partial Failure
@frappe.whitelist()
def bulk_update(items):
items = frappe.parse_json(items)
results = {"success": [], "failed": []}
for item in items:
try:
doc = frappe.get_doc("Item", item["name"])
doc.update(item)
doc.save()
results["success"].append(item["name"])
except Exception as e:
results["failed"].append({
"name": item["name"],
"error": str(e)
})
frappe.db.commit()
return results
Client-Side Patterns
frappe.call Error Handling
frappe.call({
method: "myapp.api.update_status",
args: { docname: "DOC-001", status: "Submitted" },
callback: function(r) {
if (r.message && r.message.success) {
frappe.show_alert({message: __("Updated"), indicator: "green"});
}
},
error: function(r) {
// Called on HTTP error or frappe.throw
frappe.msgprint({
title: __("Error"),
message: r.message || __("Operation failed"),
indicator: "red"
});
}
});
async/await Pattern
async function updateDocument(docname, status) {
try {
const result = await frappe.xcall("myapp.api.update_status", {
docname: docname,
status: status
});
return result;
} catch (error) {
console.error("API Error:", error);
frappe.throw(__("Failed to update document"));
}
}
External API Pattern
import requests
def call_external_api(endpoint, data):
try:
response = requests.post(
endpoint,
json=data,
timeout=30,
headers={"Authorization": f"Bearer {get_api_key()}"}
)
response.raise_for_status()
return response.json()
except requests.Timeout:
frappe.log_error("External API timeout", "API Integration")
frappe.throw(_("External service timeout. Please try again."))
except requests.HTTPError as e:
frappe.log_error(f"HTTP {e.response.status_code}", "API Integration")
frappe.throw(_("External service error"))
except requests.RequestException as e:
frappe.log_error(str(e), "API Integration")
frappe.throw(_("Connection failed"))
Critical Rules
✅ ALWAYS
- Validate input before processing
- Use
frappe.throw()for user-facing errors - Log unexpected errors with
frappe.log_error() - Return structured responses from APIs
- Handle both success and error in callbacks
❌ NEVER
- Expose internal error details to users
- Catch exceptions without logging
- Return raw exception messages
- Assume API calls will succeed
- Skip input validation
Quick Reference: Error Responses
# User-facing error (shows alert)
frappe.throw(_("Clear error message"))
# Permission error (403)
frappe.throw(_("Not allowed"), frappe.PermissionError)
# Validation error (400)
frappe.throw(_("Invalid input"), frappe.ValidationError)
# Log error (no user message)
frappe.log_error(frappe.get_traceback(), "Error Title")
Reference Files
| File | Contents |
|---|---|
| patterns.md | Detailed error handling patterns |
| examples.md | Complete working examples |
| anti-patterns.md | Common mistakes to avoid |
See Also
erpnext-api-patterns- API implementation patternserpnext-syntax-whitelisted- Whitelisted method syntaxerpnext-errors-serverscripts- Server Script error handling
Score
Total Score
75/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
✓説明文
100文字以上の説明がある
+10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon

