Before you start
Most File Storage issues come down to one of three things: the module is not enabled, you are missing a permission, or a share link has reached the end of its life. This page walks through each symptom, explains what File Storage is actually doing, and tells you what to change or who to ask.
Missing menuUpload & shareDead links Delete behaviorScanningGlossary
"I don't see File Storage"
File Storage lives in the left menu under the Storage group. If it is not there, work through these in order:
| Cause | What is happening | Fix |
|---|---|---|
| Module is off | The module_file_storage setting is not enabled for this tenant, so the menu, controllers, and jobs stay hidden. | An admin enables the module, then runs php erpat migrate:modules to create the tables. |
| No base permission | Your role lacks the file_storage permission, so the menu entry is filtered out for you even though the module is on. | An admin grants the File Storage base permission to your role. |
| Migrations not run | The module was enabled but its tables were never created, so the workspace cannot load. | An admin runs php erpat migrate:modules. |
| Wrong workspace | You are looking for governance controls but only have the base permission. | The Governance console is a separate screen and needs the high-risk governance permissions — see below. |
file_storage_view_activity, _manage_quarantine, _manage_policies, _legal_hold, _purge). These are granted separately from everyday file access."I can't upload or share"
Uploads
| Symptom | Likely cause | Fix |
|---|---|---|
| Upload button missing / drag-drop ignored | You lack file_storage_create, or your access level on this folder is below contributor. | Ask the folder or space owner for contributor access or higher; ask an admin for the create permission. |
| File rejected on the way in | Intake validation blocked it — the extension, MIME type, or file signature (magic bytes) failed ERPat's standard file checks, or a purpose policy disallows that type. | Confirm the file is an allowed type; check with an admin what the Policies registry permits for that space. |
| Upload "stuck" / not visible yet | The file is validated and queued; the upload pipeline finalizes it asynchronously. | Wait a moment and refresh — the file_storage_upload_pipeline job runs every minute. Persistent stalls: escalate to support. |
| Upload held for review | A policy routed it to quarantine for a governance reviewer. | A governance reviewer approves or rejects it in Governance → Quarantine. |
Sharing
| Symptom | Likely cause | Fix |
|---|---|---|
| No "Share internally" option | Missing file_storage_share_internal. | Ask an admin to grant internal sharing. |
| No "Create link" / external share | Missing file_storage_share_external. | External sharing is a separate, higher-trust permission — ask an admin. |
| Can't change who can access a folder | Missing file_storage_manage_permissions, or you are not a manager/owner of that folder or space. | Only managers/owners (or holders of the manage-permissions right) can edit ACLs. |
| Can't create a team space or file request | Missing file_storage_create_space or file_storage_create_file_request. | Ask an admin. Note a space always needs at least two managers. |
"The share link says not found"
A public share link stops working the moment it is no longer valid. File Storage never stores the raw link token — only a SHA-256 hash of it — so a link that has ended simply resolves to "not found." The everyday reasons:
| Reason | What happened | What to do |
|---|---|---|
| Expired | The link passed its expiry date/time. The file_storage_access_expirer job (every 5 minutes) retires expired links. | The owner creates a new link with a later expiry. |
| Revoked | The owner or an admin manually turned the link off. | Ask the owner to issue a fresh link if access is still appropriate. |
| Max opens reached | The link had an open/download limit and it was hit. The counter is enforced atomically, so it stops exactly at the cap. | The owner creates a new link (optionally with a higher or no limit). |
| Re-issued | Someone used Get new link on that share. Because the raw token is never stored, handing a link out again means replacing it — so the URL you were given stopped working the instant the new one was generated. The share itself (who can access, expiry, open limit) is unchanged. | Ask that person for the current link. Note the open counter is not reset by re-issuing, so a share already at its cap cannot be re-issued at all. |
Link opens but won't let me in
| Symptom | Cause | Fix |
|---|---|---|
| Asks for a password | The link is protected by an Argon2id-hashed password. | Get the password from the sender (over a separate channel). |
| Asks for an email code (OTP) | The link requires email one-time-password verification. | Enter your email, then the code sent to it. Check spam if it doesn't arrive. |
| Preview only, no download | Downloading was switched off for this link. | Ask the owner to enable download, or send the file another way. |
| Only lets me upload | It is an upload-only file request, not a share of an existing file. | Use it to submit files back — it is working as intended. |
| Recipient not recognized | The link scope is restricted (tenant / named external recipients) and you are outside it. | Ask the owner to widen the scope or add you as a recipient. |
"A file won't permanently delete"
This is intentional. File Storage deletes in two stages and refuses an unsafe permanent purge:
- Soft delete first. Deleting a file moves it to Trash, where it is fully recoverable.
- Reference-aware safe purge. Permanent removal only happens through the
file_storage_safe_purgejob (daily) or a governance purge — and it is fail-closed: if anything still needs the bytes, the purge is blocked.
A purge is refused while any of these hold true:
| Blocker | Meaning |
|---|---|
| Active reference | The reference ledger shows another record still points at the underlying bytes. |
| Current version | The version being purged is still the live version of a file. |
| Retention | A purpose policy's retention window has not elapsed. |
| Legal hold | An active legal hold pins the file so it cannot be purged. |
"Are my files scanned for malware?"
Short answer: every upload is validated, but there is no antivirus engine scanning contents today.
| Check | Status | Detail |
|---|---|---|
| Intake validation | Active | Extension, MIME type, and magic-byte signature checks — ERPat's existing file-security pipeline — run on every upload. |
| Quarantine routing | Active | Policies can hold uploads for human review in the Governance console before they go live. |
| AV / CDR engine | Not enabled | A pluggable scanner hook (File_scanner_service) exists, but real antivirus / content-disarm scanning is a future integration that is not switched on. |
Glossary
| Term | Meaning |
|---|---|
| Node | A logical item in the workspace — a folder or a file (row in file_nodes). What you see and organize in the tabs. |
| Version | An immutable snapshot of a file's bytes. Each new upload/restore adds a version (file_versions) rather than overwriting; history is preserved. |
| Reference ledger | The record (general_file_references) of who/what still points at a set of physical bytes. It is what makes safe purge reference-aware. |
| Purpose policy | A registry rule governing what a file is for — allowed types, retention window, and whether uploads need review. |
| Legal hold | A compliance lock that pins files so they cannot be permanently purged until the hold is released. |
| Quarantine | A holding area where policy-flagged uploads wait for a governance reviewer to approve or reject them. |
| Space | A tenant-owned Team Space — a shared area with its own membership (at least two managers) and department sync, separate from personal My Files. |
| ACL | The access list on a folder or space. Roles range from viewer through commenter, contributor, editor, manager, to owner (plus upload-only), inherited down the tree. |
Still stuck? Escalate to support
If none of the above resolves it, contact the ERPat Team. To speed things up, include:
- What you were trying to do (upload, share, download, delete) and the exact message you saw.
- The file or folder name, and which tab or space it lives in (My Files, a specific Team Space, Trash, etc.).
- For a share link: whether it was expired, revoked, hit its open limit, or asked for a password/OTP.
- Your role and, if known, which permissions you have.
- Roughly when it happened — administrators can cross-check the Activity feed and
system_logsaudit trail.