frappe-agent-architect
Use when designing multi-app Frappe architectures, deciding whether to split functionality into separate apps, or implementing cross-app communication…
Use when debugging or handling permission errors in Frappe/ERPNext. Prevents broken document access from throwing in permission hooks. Covers PermissionError (403), has_permission hook failures, User Permission restricting too much or too little, perm_level blocking field
$ npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-errors-permissions --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/frappe-errors-permissionsContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when debugging or handling permission errors in Frappe/ERPNext. Prevents broken document access from throwing in permission hooks. Covers PermissionError (403), has_permission hook failures, User Permission restricting too much or too little, perm_level blocking field
name: frappe-errors-permissions description: > Use when debugging or handling permission errors in Frappe/ERPNext. Prevents broken document access from throwing in permission hooks. Covers PermissionError (403), has_permission hook failures, User Permission restricting too much or too little, perm_level blocking field access, System Manager bypass not working, Guest access denied, sharing permissions not applying, permission_query_conditions breaking get_list, owner-based permissions confusion, Apply User Permission checkbox behavior, and the permission debug workflow using frappe.permissions.get_doc_permissions. Keywords: PermissionError, has_permission, permission_query_conditions,, permission denied, cannot access, user blocked, sharing not working, role not enough. User Permission, perm_level, sharing, guest access, owner permission. license: MIT compatibility: "Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16." metadata: author: OpenAEC-Foundation version: "2.0"
For permission system overview see `frappe-core-permissions`. For hook syntax see `frappe-syntax-hooks`.
---
| Error Message | Cause | Fix | |---------------|-------|-----| | `frappe.exceptions.PermissionError` | User lacks role or doc-level access | Add role in Role Permissions Manager or grant User Permission | | "Not permitted" on document open | `has_permission` hook returns False or role missing read | Check `frappe.permissions.get_doc_permissions(doc, user)` output | | List view shows 0 records | `permission_query_conditions` returns overly restrictive SQL | Debug the SQL condition; check User Permissions for the Link field | | "Not allowed to access ... for Guest" | Endpoint missing `allow_guest=True` or DocType lacks Guest read | Add `allow_guest=True` to `@frappe.whitelist()` | | Field invisible despite role having read | `perm_level` > 0 on field and role lacks that level | Add role permission row for the specific `perm_level` | | "User Permission restriction" blocking | User Permission on a Link field auto-filters documents | Uncheck "Apply User Permissions" on that role row or add matching User Permission | | Sharing not granting access | Sharing adds access but never overrides role absence | User MUST have base role permission; sharing only adds doc-level grants | | `ignore_permissions` has no effect | Flag set after `get_doc` already checked permissions | Set `flags.ignore_permissions = True` BEFORE calling `save()` or `insert()` | | System Manager cannot access | Custom `has_permission` hook denies without checking role | ALWAYS check for System Manager / Administrator in hook |
---
Permission error occurred
├── Document-level (single doc access)?
│ ├── has_permission hook returning False?
│ │ └── Debug: frappe.permissions.get_doc_permissions(doc, user)
│ ├── User Permission restricting Link field?
│ │ └── Check: frappe.get_all("User Permission", filters={"user": user})
│ ├── perm_level blocking field?
│ │ └── Check: role has permission row for that perm_level
│ └── Sharing not applying?
│ └── Check: user has base role + sharing record exists
├── List-level (0 records in list view)?
│ ├── permission_query_conditions returning bad SQL?
│ │ └── Debug: run condition manually in MariaDB console
│ ├── User Permission auto-filtering?
│ │ └── Check "Apply User Permissions" checkbox on role row
│ └── get_all vs get_list confusion?
│ └── ALWAYS use get_list for user-facing queries
├── API endpoint (403 response)?
│ ├── Missing @frappe.whitelist()?
│ │ └── Add decorator to Python method
│ ├── Missing allow_guest=True?
│ │ └── Add allow_guest parameter for public endpoints
│ └── frappe.only_for() blocking?
│ └── Check user has required role
└── System Manager bypass failing?
└── Custom hook does not check for System Manager role---
# hooks.py
has_permission = {
"Sales Order": "myapp.permissions.sales_order_has_permission",
}# WRONG — Breaks ALL document access
def sales_order_has_permission(doc, user, permission_type):
if doc.status == "Locked":
frappe.throw("Locked") # NEVER do this
# CORRECT — Return False to deny, None to defer
def sales_order_has_permission(doc, user, permission_type):
"""
ALWAYS wrap in try/except. NEVER throw. NEVER return True.
Returns: False (deny) or None (defer to standard system).
"""
try:
user = user or frappe.session.user
if user == "Administrator":
return None
# ALWAYS check System Manager early
if "System Manager" in frappe.get_roles(user):
return None
# Deny write on locked docs (but allow read)
if permission_type in ("write", "delete", "cancel"):
if doc.get("status") == "Locked":
return False
return None # Defer to standard permission system
except Exception:
frappe.log_error(frappe.get_traceback(),
f"has_permission error: {getattr(doc, 'name', 'unknown')}")
return None # Safe fallback — defer**Critical rules for has_permission hooks:**
# hooks.py
permission_query_conditions = {
"Sales Order": "myapp.permissions.sales_order_query",
}# WRONG — Breaks list view for all users
def sales_order_query(user):
if not user:
frappe.throw("User required") # NEVER d60 deterministic Claude AI skills for Frappe Framework & ERPNext v14-v16 development and operations
Repo: Impertio-Studio/Frappe_Claude_Skill_Package
Use when designing multi-app Frappe architectures, deciding whether to split functionality into separate apps, or implementing cross-app communication…
Use when debugging Frappe errors, using bench console for live inspection, analyzing tracebacks, or reading Frappe log files. Prevents wasted debugging time…
Use when receiving vague or unclear ERPNext/Frappe development requests that need interpretation. Transforms requirements like 'make invoice auto-calculate' or…
Use when migrating a Frappe app between major versions, detecting breaking API changes, or resolving post-migration errors. Prevents failed migrations from…
Use when reviewing or validating Frappe/ERPNext code against best practices and common pitfalls. Checks generated code before deployment, validates against all…
Use when building ERPNext/Frappe API integrations (v14/v15/v16) including REST API, RPC API, authentication, webhooks, and rate limiting. Covers external API…