{"record":{"id":"41e856830c922d4c","repo":"passbolt/passbolt_api","slug":"no-permission-found-for-folder-id-0","errorCode":null,"errorMessage":"No permission found for folder ID {0}","messagePattern":"No permission found for folder ID (.+?)","errorType":"exception","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4FoldersToV5Service.php","lineNumber":104,"sourceCode":"            ->toArray();\n\n        if (empty($folders)) {\n            $this->addError(['error_message' => __('No folders to migrate.')]);\n\n            return $this->getResult();\n        }\n\n        foreach ($folders as $folder) {\n            $dto = MetadataFolderDto::fromArray($folder->toArray());\n\n            try {\n                if ($dto->isV5()) {\n                    $msg = __('Folder ID \"{0}\" is already V5', $folder->id);\n                    throw new InternalErrorException($msg);\n                }\n                if (count($folder->permissions) === 0) {\n                    $msg = __('No permission found for folder ID {0}', $folder->id);\n                    throw new InternalErrorException($msg);\n                }\n\n                if (count($folder->permissions) === 1) {\n                    $this->migratePersonal($dto, $folder);\n                } else {\n                    $this->migrateShared($dto, $folder);\n                }\n                $this->addMigrated($folder);\n            } catch (Exception $e) {\n                // Continue with next resource if any error\n                $error = ['folder_id' => $folder->id, 'error_message' => $e->getMessage()];\n                if (Configure::read('debug')) {\n                    $error['trace'] = $e->getTraceAsString();\n                }\n                $this->addError($error);\n            }\n        }\n","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4FoldersToV5Service.php#L86-L122","documentation":"The V4-to-V5 folder migration requires every folder to have at least one permission (a personal folder needs its owner's permission to know whose key encrypts the metadata). If the loaded folder's permissions collection is empty, an InternalErrorException naming the folder ID is thrown from migrate().","triggerScenarios":"Migrating a folder that exists in the folders table but has zero rows in permissions — orphaned folder data from cascading permission deletions, manual DB edits, or restore inconsistencies.","commonSituations":"Databases where permissions were removed without deleting the folder; partially restored backups; folders inherited visibility through ACL cleanup gone wrong.","solutions":["Delete or repair the orphaned folder(s) — restore permissions for the folder identified in the message.","Re-grant an owner permission to the folder, then re-run the migration.","Skip folders with no permissions (log their IDs) so the batch can continue and address them manually.","Audit with SQL: folders left-joined to permissions where permissions.id IS NULL."],"exampleFix":"// before: any folder is processed\n$folders = $foldersTable->find()->contain('Permissions')->all();\n// after: require at least one permission\n$folders = $foldersTable->find()\n    ->innerJoinWith('Permissions')\n    ->distinct()\n    ->contain('Permissions')->all();","handlingStrategy":"validation","validationCode":"$orphanFolders = TableRegistry::getTableLocator()->get('Folders')\n    ->find()\n    ->notMatching('Permissions')\n    ->all(); // repair or delete these before migrating","typeGuard":"if (count($folder->permissions) === 0) { continue; } // skip and log","tryCatchPattern":"try {\n    $service->migrate($uac);\n} catch (\\Cake\\Http\\Exception\\InternalErrorException $e) {\n    if (str_starts_with($e->getMessage(), 'No permission found for folder')) {\n        // repair the folder identified in the message\n    }\n}","preventionTips":["Never delete permissions without deleting or reassigning the folder","Run data-integrity checks (folders without permissions) before migrations","Validate backups/restores leave permissions consistent with folders"],"tags":["migration","permissions","folders","data-integrity"],"backgroundTag":"empty-required-field","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"}