{"record":{"id":"3d2c14b2a92ffbcd","repo":"passbolt/passbolt_api","slug":"could-not-save-secret-revision","errorCode":null,"errorMessage":"Could not save secret revision","messagePattern":"Could not save secret revision","errorType":"validation","errorClass":"CustomValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/SecretRevisions/src/Service/CreateSecretRevisionsService.php","lineNumber":79,"sourceCode":"            'accessibleFields' => [\n                'resource_id' => true,\n                'resource_type_id' => true,\n                'created_by' => true,\n                'modified_by' => true,\n            ],\n        ]);\n        $secretRevision->secrets = $resource->secrets;\n        // For performance, we explicitly set the fields of the secrets as non-accessible, so the data for example\n        // of the secret is not persisted again.\n        // The goal here is only to persist the secret_revision_id field\n        foreach ($secretRevision->secrets as $secret) {\n            $secret->setAccess('*', false);\n        }\n        $secretRevision->setDirty('secrets');\n        /** @var \\Passbolt\\SecretRevisions\\Model\\Entity\\SecretRevision $secretRevision */\n        $secretRevision = $this->SecretRevisions->save($secretRevision);\n        if (!$secretRevision) {\n            throw new CustomValidationException(__('Could not save secret revision'), $secretRevision->getErrors());\n        }\n\n        return $secretRevision;\n    }\n\n    /**\n     *  - Soft delete the previous secret revision and secrets\n     *  - creates a secret revision on resource update and associates it to:\n     * - the resource passed as parameter\n     * - the secrets associated to this resource\n     *\n     * @param \\App\\Model\\Entity\\Resource $resource the resource being saved\n     * @return \\Passbolt\\SecretRevisions\\Model\\Entity\\SecretRevision\n     */\n    public function createNewRevision(Resource $resource): ?SecretRevision\n    {\n        if (empty($resource->secrets)) {\n            return null;","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/SecretRevisions/src/Service/CreateSecretRevisionsService.php#L61-L97","documentation":"Thrown by CreateSecretRevisionsService::createFirstRevision() when SecretRevisions->save($secretRevision) returns falsy during creation of a resource's first secret revision; CustomValidationException carries the entity errors (HTTP 422-style validation response). Note the errors are read from the post-save (possibly replaced) entity, which can mask the real errors.","triggerScenarios":"Creating the first secret revision for a new resource where the SecretRevisions table rejects the entity — invalid foreign keys (resource_id/secret_id), missing required fields, association save (secrets) failure, or rules such as unique revision constraints failing.","commonSituations":"Resource or secret not persisted before the revision save (ordering bug); data violating SecretRevisions validation rules (empty data, bad timestamps); database constraint violations surfaced as validation errors; schema drift after missing migrations.","solutions":["Capture $errors = $this->SecretRevisions->getErrors() before save and log them to see which field failed","Ensure the associated Resource/Secret entities are persisted and have valid IDs before creating the revision","Run pending migrations so the secret_revisions table exists with correct constraints","Verify the payload passed into the revision (data, secrets association) satisfies the table's validation rules"],"exampleFix":"// before\n$secretRevision = $this->SecretRevisions->save($secretRevision);\nif (!$secretRevision) {\n    throw new CustomValidationException(__('Could not save secret revision'), $secretRevision->getErrors());\n}\n// after\n$errors = $secretRevision->getErrors();\n$secretRevision = $this->SecretRevisions->save($secretRevision);\nif (!$secretRevision) {\n    throw new CustomValidationException(__('Could not save secret revision'), $errors);\n}","handlingStrategy":"try-catch","validationCode":"$errors = $secretRevision->getErrors();\nif ($errors) { throw new CustomValidationException(__('Invalid secret revision'), $errors); }\nif (!$resource->id || !$secret->id) { throw new \\InvalidArgumentException('Resource and secret must be persisted first'); }","typeGuard":null,"tryCatchPattern":"try {\n    $revision = $service->createFirstRevision($uac, $resourceId, $secrets);\n} catch (CustomValidationException $e) {\n    Log::error('Revision validation failed', ['errors' => $e->getErrors()]);\n}","preventionTips":["Persist parent Resource/Secret entities before creating revisions","Capture entity errors BEFORE save() so errors aren't lost","Run migrations so secret_revisions constraints exist","Log full validation errors for failed saves"],"tags":["validation","cakephp","save-failure"],"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"}