{"record":{"id":"e3602d30dae711e7","repo":"phalcon/cphalcon","slug":"role-rolename-to-inherit-does-not-exist-in-t","errorCode":null,"errorMessage":"Role '{roleName}' (to inherit) does not exist in the role list","messagePattern":"Role '(.+?)' \\(to inherit\\) does not exist in the role list","errorType":"exception","errorClass":"Phalcon\\Acl\\Exceptions\\RoleNotFoundException","httpStatus":null,"severity":"error","filePath":"phalcon/Acl/Adapter/Memory.zep","lineNumber":330,"sourceCode":"        for roleToInherit in roleToInheritList {\n            if typeof roleToInherit === \"object\" && roleToInherit instanceof RoleInterface {\n                let roleInheritName = roleToInherit->getName();\n            } else {\n                let roleInheritName = roleToInherit;\n            }\n\n            /**\n             * Check if the role to inherit is repeat\n             */\n            if in_array(roleInheritName, this->roleInherits[roleName]) {\n                continue;\n            }\n\n            /**\n             * Check if the role to inherit is valid\n             */\n            if unlikely !isset this->roles[roleInheritName] {\n                throw new RoleNotFoundException(roleInheritName);\n            }\n\n            if roleName == roleInheritName {\n                return false;\n            }\n\n            /**\n             * Deep check if the role to inherit is valid\n             */\n            if isset this->roleInherits[roleInheritName] {\n                let checkRoleToInherits = [];\n\n                for usedRoleToInherit in this->roleInherits[roleInheritName] {\n                    array_push(checkRoleToInherits, usedRoleToInherit);\n                }\n\n                let usedRoleToInherits = [];\n","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Acl/Adapter/Memory.zep#L312-L348","documentation":"Thrown during QueryBuilderCursor::paginate() (InvalidCursorColumn) when a next page was detected (limit + 1 rows returned) and the last kept row's cursor column value is not numeric. Keyset pagination compares 'column > :cursor:' and casts the cursor to int; a non-numeric value (e.g. a UUID string) would silently cast to 0 and terminate pagination, so it is rejected explicitly. Note the message reuses the constructor's 'non-empty string' wording — here the real problem is the column VALUE, not the column name.","triggerScenarios":"Setting 'cursorColumn' => 'uuid' (or any string-typed key such as a UUID/BIN column) on a table whose values are non-numeric, then calling paginate() on a result set larger than one page.","commonSituations":"Tables with UUID primary keys; cursor columns chosen as CHAR(36) identifiers; models whose selected column is typecast to string in the resultset.","solutions":["Use a numeric monotonic column as cursorColumn — typically the auto-increment primary key ('id').","If rows only have UUIDs, add a numeric surrogate column (auto-increment or sequence/bigint) and paginate on that.","If UUID cursors are mandatory, use the offset-based QueryBuilder adapter instead, which does not keyset-compare the column."],"exampleFix":"// before\n$paginator = new QueryBuilderCursor(\n    [\n        'limit'        => 20,\n        'builder'      => $builder->orderBy('uuid'),\n        'cursorColumn' => 'uuid', // UUIDs are not numeric\n    ]\n);\n$paginator->paginate(); // throws InvalidCursorColumn on page detection\n\n// after\n$builder->orderBy('id');\n$paginator = new QueryBuilderCursor(\n    [\n        'limit'        => 20,\n        'builder'      => $builder,\n        'cursorColumn' => 'id', // numeric auto-increment column\n    ]\n);","handlingStrategy":"validation","validationCode":"// Keyset cursor must be numeric: verify against the model metadata\n$metadata = new \\Phalcon\\Storage\\SerializerFactory(); // placeholder\n$columnMap = $model->getModelsMetaData()->getDataTypes($model);\n$type = $columnMap[$cursorColumn] ?? null;\n$numericTypes = [\n    \\Phalcon\\Db\\Column::TYPE_INTEGER,\n    \\Phalcon\\Db\\Column::TYPE_BIGINTEGER,\n    \\Phalcon\\Db\\Column::TYPE_SMALLINTEGER,\n    \\Phalcon\\Db\\Column::TYPE_TINYINTEGER,\n    \\Phalcon\\Db\\Column::TYPE_MEDIUMINTEGER,\n    \\Phalcon\\Db\\Column::TYPE_FLOAT,\n    \\Phalcon\\Db\\Column::TYPE_DOUBLE,\n];\nif ($type === null || !in_array($type, $numericTypes, true)) {\n    throw new \\InvalidArgumentException(\n        \"cursorColumn '{$cursorColumn}' must map to a numeric DB column\"\n    );\n}","typeGuard":"function isNumericCursorValue(mixed $value): bool\n{\n    return is_numeric($value); // mirrors the adapter's is_numeric() check at paginate()\n}","tryCatchPattern":null,"preventionTips":["Choose a numeric auto-increment column as the cursor for QueryBuilderCursor.","UUID-keyed tables need a numeric surrogate column or the offset-based QueryBuilder adapter.","Add a first-page smoke test: paginate() on a result set larger than one page to exercise the cursor path."],"tags":["paginator","cursor","uuid","type-mismatch"],"backgroundTag":"keyset-pagination-cursor-type","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}