FAQ & Troubleshooting
The questions IT admins, custodians, and employees ask most often about the Assets (Safekeep) module — with the exact on-screen messages, the reason behind each behavior, and what to do about it. Finish with the message lookup table if you only remember the wording you saw.
Setup & access
The whole Safekeep sidebar group appears only when both conditions hold:
- The Assets module is enabled — Settings → Manage Modules → Assets (Safekeep category).
- Your role grants the base permission
asset(Assets: Entries in the Roles editor, category "Safekeep: Assets").
Every Safekeep menu item is gated on that same asset permit, so without it
the group vanishes entirely. See Getting Started for
enablement and Permissions & Roles for the full RBAC table.
Two separate permits, both in the Roles editor under "Safekeep: Assets":
- Assets — the row-action "Delete" on the Asset Registry needs
asset_delete(Delete Asset). Deletion is a soft delete with a confirmation prompt; success shows "The record has been deleted." - Comments — the "Delete" item in a comment's chevron dropdown needs
delete_asset_comment(Assets: Delete Entry Comments).
delete_asset_comment, static comments can never be
deleted — the pinned Description comment and the automatic edit change-log entries
("Title changed to…", "Issued to updated from… to…") are permanent parts of the record.
Catalog records (Models, Status Labels, Custom Fields, Fieldsets, Depreciations) have
no separate delete permits — anyone with the base asset permission can
delete them, and there are no in-use checks. Delete carefully; see
Permissions & Roles.
"Clone" (in the asset row's hamburger dropdown on the Asset Registry) is admin-only — it is not controlled by any permission key, only by the administrator flag on your account. Non-admins see "Edit" and "Delete" (per their permits) but never Clone.
Clone opens the same modal as Add with a "Duplicate" count field (minimum 1) so an admin can create N copies in one save. See Adding & Editing Assets.
The Assets modularization renamed and consolidated the old sidebar entries. The shipped Safekeep group now has six items — Assets, Categories, Depreciations, Custom Fields, Maintenance, Asset Reports — and everything else became an in-page tab. Mapping from the old names:
| Old sidebar item | Where it lives now |
|---|---|
| Asset Entries | Assets sidebar item (ams/assets) — the Asset Registry Browse tab |
| Asset Category | Categories sidebar item (ams/categories) — see Categories |
| Asset Location | Location tab on the Assets page (Locations) |
| Asset Groups | Groups tab on the Categories page (Asset Groups) |
| Asset Models | Models tab on the Assets page (Asset Models) |
| Status Labels | Status Labels tab on the Categories page (Status Labels) |
| Fieldsets | Fieldsets tab of the Custom Fields page (Custom Fields & Fieldsets) |
| Asset Vendors | Shared Vendors page at ams/vendors (core screen, not module-owned) |
| Asset Brands | Shared Brands page at ams/brands — the "Manufacturer" source (core screen) |
A data migration rewrites saved left-menu customizations automatically: the old
asset_entries item is renamed to assets, dead item names are
dropped, and the new Safekeep items are spliced in — so customized menus regain the full
group without manual editing.
During the module's build-out, Fieldsets, Status Labels, and Models were briefly their own sidebar items, so a menu saved in that window may still carry them. In the shipped module they are not menu items at all:
- Fieldsets is the "Fieldsets" tab of the Custom Fields page (
ams/custom_fields) — see Custom Fields & Fieldsets. - Status Labels is the "Status Labels" tab of the Categories page (
ams/categories) — see Status Labels.
The module's default-menu slice (what "Restore to default" in Left Menu Customization rebuilds) contains only the six current Safekeep items, so any stale Fieldsets/Status Labels menu entry disappears on restore — and the saved-menu remap migration drops the stale names too. Nothing is lost: the screens are always reachable through their tabs, regardless of your menu customization.
Not inside this module. Both are shared masters reused across ERPat:
- Vendors / Suppliers — the shared Vendors screen at
ams/vendors(corevendorpermission). The asset form's "Vendor" dropdown and the Maintenance form's "Vendor" dropdown both read this table. - Manufacturers — the shared Brands screen at
ams/brands(corebrandpermission). The Asset Model form's "Manufacturer" dropdown lists brands flagged for assets.
Their permissions therefore live in the core Roles list, not under "Safekeep: Assets". If a vendor or manufacturer is missing from a dropdown, add it on those shared screens first — or let the importer auto-create it by name.
Lifecycle
Checkout (the "Check out asset" action on the asset detail page) can be blocked for three reasons:
- You lack the permit. The action needs
asset_checkout(Assets: Checkout / Endorse) — without it the menu item never appears. - The asset is already endorsed to someone.
- The asset's status label is not Deployable.
asset_already_checked_out) and
"This asset's status is not deployable, so it cannot be checked out."
(asset_not_deployable)
What "deployable" means: every status label carries one of four deploy types — Deployable Pending Undeployable Archived. Only a Deployable status allows checkout. Of the seven seeded labels, only Ready to Deploy and Deployed are Deployable; Pending, In Repair, Broken, Lost / Stolen, and Archived all block checkout.
What to do: if the asset is with someone else, check it in first; if the status blocks it, edit the asset (or use check-in's "Set status to") to a Deployable label such as "Ready to Deploy", then check out again. Note an asset with no status at all skips the deployability guard entirely. Checkout targets are staff users only — there is no checkout-to-location or asset-to-asset endorsement. Full walkthrough: Checkout & Check-in.
"Confirm receipt" is an assignee-only action — it has no permission key. The menu item appears on the asset detail page only when all three hold:
- You are the asset's current assignee (it is endorsed to you), and
- the asset is currently checked out, and
- you have not yet acknowledged it.
No one else — including users with full checkout rights — sees the button, because
acknowledgment is the recipient's personal sign-off in the chain of custody. (The server
does accept an administrator submitting the confirmation on the assignee's behalf, but the
shipped page shows the button only to the assignee.) If the asset is not assigned at all,
the action refuses with "This asset is not currently assigned."
(asset_not_assigned). The same assignee-only rule applies to the
"Request return" button. See Checkout & Check-in.
The acknowledge modal shows the scrollable "Acceptance agreement" box, the required checkbox "I have read and accept the terms above.", and the signature field "Type your full name to sign" only when the asset's category has acceptance enabled. Otherwise the modal is just a plain "Confirm receipt" confirmation.
asset_categories.require_acceptance and eula_text) can only be
set directly in the database — the Category form has
no inputs for them. Until a database administrator sets them, no asset will ever show an
EULA on acknowledge. This is expected behavior, not a bug.
When acceptance is enabled, skipping the checkbox or signature is rejected with "Please tick the box to accept the terms." / "Please type your full name to accept the agreement.", and the accepted EULA copy and typed signature are frozen onto the event record. Details: Checkout & Check-in.
Asset comments are delete-only — the comment dropdown has a single
"Delete" item (shown with the delete_asset_comment permit) and no edit
option. To correct a comment, delete it and post a new one. Static comments (the pinned
Description and automatic change-log entries) cannot be deleted at all.
Comment sort order (newest-first vs oldest-first) and who can be @-mentioned are controlled by the core screen Settings → Asset Entries Configuration ("Sort Asset Entry Comments" and "Allowed users to mention"). See Asset Detail & Activity.
It isn't there — the asset detail page has no per-asset maintenance list. To see maintenance work:
- The Maintenance screen (Safekeep → Maintenance) lists every record with asset, type, vendor, dates, cost, and warranty-work flag.
- The Maintenance log report under Asset Reports shows the same read-only.
- The asset's Activity timeline shows a "Maintenance" event for each maintenance record when it was created — but later edits or deletion of the maintenance record do not update that timeline entry.
Catalog
By design, the asset detail page shows only the header, the sub-title strip (category / vendor / type / brand / model / serial / location), the lifecycle summary, the Activity timeline, and comments. It does not display the photo, cost, purchase date, warranty, order number, condition, or the "Additional fields" (custom-field) values.
Where to find them instead:
- Edit modal — open Actions → Edit (needs
asset_update); every stored field is there, including the per-category "Additional fields" block and the attached photo. See Adding & Editing Assets. - XLSX export — "Export Assets" (needs
asset_export) exports cost, purchase date, warranty, order number, notes, image filename, plus every custom field by its label. See Import, Export & Labels. - Cost, purchase date, and warranty expiry are also columns on the Asset Registry Browse table.
Custom fields never attach to assets directly. The chain is: Custom Field → bundled into a Fieldset (Custom Fields page → Fieldsets tab) → the Fieldset is bound to a Category ("Fieldset" dropdown in the Category form) → assets in that category show the fields as "Additional fields".
If a field is missing, check each link in that chain — and make sure the asset actually has the right Category selected (changing the category re-renders the block). Required fields reject saves with "%s is required."; number fields with "%s must be a number." Full chain: Custom Fields & Fieldsets and Categories.
No. Track only what ships: asset entries, models, categories, locations, groups, status labels, custom fields/fieldsets, depreciations, maintenance, audits, and the endorsement lifecycle.
asset_accessories database table exists, but there is no screen for it — do
not rely on it.)
Import & export
The import finishes with "Import complete: %d created, %d updated, %d skipped." A row is skipped when its Asset Tag already exists on a live asset and the "Update existing assets" checkbox was left off — the tag is the sole dedupe key (exact match).
What to do: re-run the import with "Update existing assets" ticked to refresh the matching rows. Two behaviors to know:
- Blank cells are ignored on update — an empty cell never wipes an existing value, so partial files are safe.
- New rows with a blank tag are never skipped — they are created and auto-assigned a tag like
AST-000123.
Rows with checkout columns whose assignee can't be matched to a staff user still import,
but unassigned (warning assignee_unresolved). Full column reference:
Import, Export & Labels.
Yes. The import modal's help block ("Import from Snipe-IT CSV") says it directly:
Categories, locations, manufacturers (brands), suppliers (vendors), status labels, and asset models named in the file are auto-created if missing, and unrecognized columns matching a category's custom-field keys/labels land in the asset's custom-field values. You can also download a clean template via the modal's "Export Excel" button. See Import, Export & Labels.
The label flow opens one browser tab per PDF page (102 labels per PDF). If your browser blocks pop-ups you'll see the alert "Please allow popups for this website" — allow pop-ups for your ERPat domain and print again. If no assets match your Category / Location filters, the modal warns "No record found." See Import, Export & Labels.
Automation
The Depreciation schedule report does no math of its own — the "Current value"
and "Computed at" columns display whatever the cron job
compute_asset_depreciation last stored. That job runs monthly, on the 1st
of the month at 01:10 — not nightly — so values are at most one month fresh, and show
"-" until the job has run at least once.
What to check:
- Your server's scheduler must actually be ticking ERPat's Advanced Cron (ask your administrator). An admin can trigger a compute on demand:
php erpat cron:run compute_asset_depreciation. - An asset is only computed if it has a depreciation schedule (via its Asset Model), a cost > 0, and a purchase date — otherwise it never appears on the report at all.
See Depreciations for the straight-line formula and Widgets, Reminders & Settings for the cron catalog.
Three reminder jobs ship enabled: return due (daily 07:00, due within 3 days), warranty expiry (daily 07:30, expiring within 30 days), and audit due (weekly Monday 08:00, due within 7 days). If nothing arrives:
- Cron must be running. The jobs only fire when the server scheduler ticks ERPat's cron. Admins:
php erpat cron:listto verify,php erpat cron:run <slug>to test (remind_asset_return_due,remind_asset_warranty_expiry,remind_asset_audit_due). - Only the asset holder is notified. Reminders go solely to the "Issued to" user — unassigned assets never generate reminders; watch those via the "Assets needing attention" widget or the Audit due report instead.
- The asset must qualify. Return-due needs a "Due / return by" date; warranty needs a future "Warranty expiry date" (already-expired ones are excluded); audit needs a "Next Audit" date.
- Personal notification preferences can mute the in-app/email channels per event.
Notification texts: "An asset assigned to you is due to be returned", "An asset's warranty is about to expire", "An asset assigned to you is due for audit" — each links to the asset's detail page. Note reminders repeat (daily/weekly) with no dedupe while the condition holds. Full details: Widgets, Reminders & Settings and Auditing Assets.
The "Assets needing attention" dashboard widget reads the setting
asset_warranty_reminder_days (default 30) for its "Warranty expiring" window,
while the reminder cron job hardcodes 30 days. If that setting has been changed in
the database (it has no settings UI), the widget and the emails will use different windows.
With the default value they agree.
Message lookup
Every guard, validation, and confirmation message quoted in this guide, in one place.
| Message (exact) | Where it appears | What it means / what to do |
|---|---|---|
"This asset is already checked out." asset_already_checked_out |
Checkout | The asset is endorsed to someone. Check it in first — see Checkout & Check-in. |
"This asset's status is not deployable, so it cannot be checked out." asset_not_deployable |
Checkout | The current status label's deploy type isn't Deployable. Set a deployable status (e.g. "Ready to Deploy") and retry. |
"This asset is not currently assigned." asset_not_assigned |
Confirm receipt / Request return / Check-in | The lifecycle action needs a current assignee; the asset has none. |
"Please tick the box to accept the terms." acceptance_terms_required |
Confirm receipt (EULA categories only) | Tick "I have read and accept the terms above." before submitting. |
"Please type your full name to accept the agreement." acceptance_signature_required |
Confirm receipt (EULA categories only) | Fill in "Type your full name to sign". |
"%s is required." meta_field_required |
Asset save (Additional fields) | A required custom field is empty. See Adding & Editing Assets. |
"%s must be a number." meta_field_invalid_number |
Asset save (Additional fields) | A Number-type custom field got non-numeric input. |
"Maximum of 3 layers parenting only" error_max_parenting |
Category / Location save | The chosen parent is already 3 levels deep — trees cap at ~4 levels. See Categories / Locations. |
"Import complete: %d created, %d updated, %d skipped." assets_imported_summary |
Import Assets | Result summary; skipped = existing Asset Tag with "Update existing assets" off. |
| "Please allow popups for this website" | Print asset labels | Browser blocked the PDF tabs — allow pop-ups and retry. |
| "No record found." | Print asset labels | No assets match the Category/Location filters. |
"No activity recorded yet." no_activity_yet |
Asset detail — Activity | Empty state: no lifecycle events on this asset yet. |
"The record has been saved." record_saved / "The record has been deleted." record_deleted |
All save/delete actions | Standard success confirmations. |
| "Asset checked out." / "Receipt confirmed." / "Return requested" / "Asset checked in." / "Audit recorded." | Lifecycle actions | Success toasts for checkout → acknowledge → request return → check-in, and audit. See Checkout & Check-in / Auditing Assets. |