{"record":{"id":"c4a75ecab4135165","repo":"passbolt/passbolt_api","slug":"could-not-validate-permission-history-data","errorCode":null,"errorMessage":"Could not validate permission history data.","messagePattern":"Could not validate permission history data\\.","errorType":"validation","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/Log/src/Model/Table/PermissionsHistoryTable.php","lineNumber":200,"sourceCode":"                'type' => true,\n            ],\n        ]);\n    }\n\n    /**\n     * Create a new permissions_history.\n     *\n     * @param array $data the data\n     * @return \\Passbolt\\Log\\Model\\Entity\\PermissionHistory\n     * @throws \\App\\Error\\Exception\\ValidationException\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException\n     */\n    public function create(array $data): PermissionHistory\n    {\n        // Check validation rules.\n        $log = $this->buildEntity($data);\n        if ($log->getErrors()) {\n            throw new ValidationException(__('Could not validate permission history data.', true), $log, $this);\n        }\n\n        $permissionHistory = $this->save($log);\n\n        // Check for validation errors. (associated models too).\n        if ($log->getErrors()) {\n            throw new ValidationException(__('Could not validate permission history data.'), $permissionHistory, $this);\n        }\n\n        // Check for errors while saving.\n        if (!$permissionHistory) {\n            throw new InternalErrorException('Could not save permission history.');\n        }\n\n        return $permissionHistory;\n    }\n}\n","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Log/src/Model/Table/PermissionsHistoryTable.php#L182-L218","documentation":"PermissionsHistoryTable::create() throws this ValidationException when the PermissionHistory entity built via buildEntity() fails validation before any save. The supplied permission history data (e.g. permission_id, type, acl_foreign_key) violates the table's rules.","triggerScenarios":"create() called with data missing required columns or with invalid values: empty permission_id, an out-of-range permission type integer, empty/invalid acl_foreign_key, or an invalid data blob format.","commonSituations":"Logging a permission change where the original permission row was incomplete; permission type constants changed between versions so the stored type no longer validates; passing an entity instead of an array to create(); missing fields not covered by the $defaultData merge.","solutions":["Inspect the entity errors included in the ValidationException for the exact failing field.","Supply all required PermissionHistory fields (permission_id, type, acl_foreign_key, etc.) matching the original permission.","Ensure the permission type is one of the valid defined type constants.","If triggered via EntitiesHistory save with associated PermissionsHistory, fix the nested association payload."],"exampleFix":"// before\n$this->PermissionsHistory->create(['permission_id' => $permissionId]);\n// after\n$this->PermissionsHistory->create([\n    'permission_id' => $permissionId,\n    'type' => $permission->type,\n    'aco' => $permission->aco,\n    'aco_foreign_key' => $permission->aco_foreign_key,\n    'aro' => $permission->aro,\n    'aro_foreign_key' => $permission->aro_foreign_key,\n]);","handlingStrategy":"validation","validationCode":"function validatePermissionHistoryData(array $data): bool { return !empty($data['permission_id']) && isset($data['type']) && is_int($data['type']) && !empty($data['acl_foreign_key']); }","typeGuard":"function isPermissionHistoryPayload(mixed $data): bool { return is_array($data) && isset($data['permission_id'], $data['type']); }","tryCatchPattern":"try { $permissionsHistoryTable->create($data); } catch (ValidationException $e) { $errors = $e->getEntity()->getErrors(); // correct the fields listed in $errors before retry\n}","preventionTips":["Build history payloads from the original Permission entity fields, not hand-picked ones.","Keep permission type constants in sync with the plugin version.","Pass arrays (not entities) to create().","Unit-test create() for every permission type your code writes."],"tags":["validation","logging","permissions","cakephp"],"backgroundTag":"schema-validation-failed","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}