{"record":{"id":"65ec85f108f67fd6","repo":"monicahq/monica","slug":"the-module-cannot-be-deleted","errorCode":null,"errorMessage":"The module cannot be deleted.","messagePattern":"The module cannot be deleted\\.","errorType":"exception","errorClass":"CantBeDeletedException","httpStatus":500,"severity":"error","filePath":"app/Domains/Settings/ManageTemplates/Services/DestroyModule.php","lineNumber":45,"sourceCode":"    {\n        return [\n            'author_must_belong_to_account',\n            'author_must_be_account_administrator',\n        ];\n    }\n\n    /**\n     * Destroy a module.\n     */\n    public function execute(array $data): void\n    {\n        $this->validateRules($data);\n\n        $module = $this->account()->modules()\n            ->findOrFail($data['module_id']);\n\n        if (! $module->can_be_deleted) {\n            throw new CantBeDeletedException('The module cannot be deleted.');\n        }\n\n        $module->delete();\n    }\n}\n","sourceCodeStart":27,"sourceCodeEnd":51,"githubUrl":"https://github.com/monicahq/monica/blob/e08e91734170b6bbd582cb578532c3948196124e/app/Domains/Settings/ManageTemplates/Services/DestroyModule.php#L27-L51","documentation":"DestroyModule deletes a template module from the account. Modules shipped or seeded with the template system are marked can_be_deleted = false and must not be removed; when findOrFail locates such a module, CantBeDeletedException aborts the delete before anything is touched.","triggerScenarios":"Calling module destroy with the id of a system/default module — one whose can_be_deleted flag is false — e.g. a module created by template seeding rather than by the user.","commonSituations":"Scripts or API clients iterating all modules and deleting each, or a frontend that renders the delete affordance for non-deletable modules.","solutions":["Delete only user-created modules; check the can_be_deleted flag first","Filter the UI/command to hide or skip modules with can_be_deleted = false","Check the flag at the call site before invoking the service and show a clear message"],"exampleFix":"// before\napp(DestroyModule::class)->execute([\n    'module_id' => $moduleId, // may be a seeded system module -> throws\n]);\n\n// after\n$module = $account->modules()->findOrFail($moduleId);\nif (! $module->can_be_deleted) {\n    throw ValidationException::withMessages([\n        'module_id' => 'This module cannot be deleted.',\n    ]);\n}\napp(DestroyModule::class)->execute(['module_id' => $module->id]);","handlingStrategy":"validation","validationCode":"// Validate before calling: only deletable modules may be destroyed\n$module = $account->modules()->findOrFail($data['module_id']);\n\nif (! $module->can_be_deleted) {\n    throw ValidationException::withMessages([\n        'module_id' => 'This module is a system module and cannot be deleted.',\n    ]);\n}","typeGuard":"function isDeletableModule(Module $module): bool\n{\n    return $module->can_be_deleted === true;\n}","tryCatchPattern":"use App\\Exceptions\\CantBeDeletedException;\n\ntry {\n    app(DestroyModule::class)->execute($data);\n} catch (CantBeDeletedException $e) {\n    // deliberate guard: inform the caller this module is protected\n    throw ValidationException::withMessages(['module_id' => $e->getMessage()]);\n}","preventionTips":["Filter module lists by can_be_deleted before rendering delete actions","In bulk operations, skip protected modules instead of aborting the run","Treat can_be_deleted = false as part of the module API surface when building UIs","Map CantBeDeletedException to 422 at the controller boundary"],"tags":["monica","templates","modules","delete-guard"],"backgroundTag":"protected-record-delete-denied","analyzedSha":"e08e91734170b6bbd582cb578532c3948196124e","analyzedAt":"2026-08-17T01:36:49.014Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}