{"record":{"id":"b6fa6146667d8ba7","repo":"passbolt/passbolt_api","slug":"could-not-save-the-tags-try-again-later-exceptionmessage","errorCode":null,"errorMessage":"Could not save the tags, try again later. {exceptionMessage}","messagePattern":"Could not save the tags, try again later\\. (.+?)","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltEe/Tags/src/Service/Tags/ResourcesTagsAddService.php","lineNumber":89,"sourceCode":"\n        // Mark modified as dirty to prevent TimestampBehavior from updating it.\n        // Tags are not part of the resource itself and should not affect the resource's modified timestamp.\n        // @see https://book.cakephp.org/5/en/orm/behaviors/timestamp.html#using-the-timestamp-behavior\n        $resource->setDirty('modified');\n\n        $saveOptions = ['associated' => ['Tags', 'Tags._joinData']];\n        try {\n            $this->Resources->saveOrFail($resource, $saveOptions);\n        } catch (PersistenceFailedException $e) { // @phpstan-ignore-line\n            throw new ValidationException(\n                __('Could not save the tags, try again later.'),\n                $resource,\n                $this->Resources\n            );\n        } catch (Exception $e) {\n            $msg = __('Could not save the tags, try again later.');\n            $msg .= ' ' . $e->getMessage();\n            throw new InternalErrorException($msg, null, $e);\n        }\n\n        $this->Tags->deleteAllUnusedTags();\n\n        $options = ['contain' => ['tag' => 1, 'permission' => 1]];\n        $resource = $this->Resources->findView($uac->getId(), $resource->id, $options)->first();\n\n        return $resource->get('tags');\n    }\n\n    /**\n     * Patch the resource tags entities of a resource for a given user.\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac User access control.\n     * @param \\App\\Model\\Entity\\Resource $resource The resource to patch the tags for\n     * @param array $data The list\n     * @return void\n     */","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Tags/src/Service/Tags/ResourcesTagsAddService.php#L71-L107","documentation":"Thrown by ResourcesTagsAddService::add when the tags save throws a generic (non-persistence) Exception; the message is 'Could not save the tags, try again later.' plus the original exception message, rethrown as InternalErrorException (500). It signals an unexpected infrastructure-level failure rather than client validation.","triggerScenarios":"Database connection loss, SQL errors, transaction failures, or any unexpected Exception during saveOrFail of the resource with associated tags.","commonSituations":"DB outages or failovers during the request; MySQL/Postgres constraint or syntax errors from schema drift; resource contention/timeouts.","solutions":["Read the appended exceptionMessage to identify the underlying database exception.","Retry the request — the message explicitly advises trying again later.","Verify database connectivity and schema migrations are up to date (ddev refresh / run migrations).","If persistent, check server logs for SQL errors and fix the schema or data causing them."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { addTags(...) } catch (InternalErrorException $e) { retryWithBackoff(3); checkDbHealth(); }","preventionTips":["Monitor database availability","Keep migrations current","Use exponential backoff on 5xx retries","Read appended exceptionMessage for root cause"],"tags":["database","tags","internal-error","retry"],"backgroundTag":"database-write-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"}