phalcon/cphalcon · error · Phalcon\Acl\Exceptions\RoleNotFoundException

Role '{roleName}' (to inherit) does not exist in the role li

Error message

Role '{roleName}' (to inherit) does not exist in the role list

What it means

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.

Source

Thrown at phalcon/Acl/Adapter/Memory.zep:330

        for roleToInherit in roleToInheritList {
            if typeof roleToInherit === "object" && roleToInherit instanceof RoleInterface {
                let roleInheritName = roleToInherit->getName();
            } else {
                let roleInheritName = roleToInherit;
            }

            /**
             * Check if the role to inherit is repeat
             */
            if in_array(roleInheritName, this->roleInherits[roleName]) {
                continue;
            }

            /**
             * Check if the role to inherit is valid
             */
            if unlikely !isset this->roles[roleInheritName] {
                throw new RoleNotFoundException(roleInheritName);
            }

            if roleName == roleInheritName {
                return false;
            }

            /**
             * Deep check if the role to inherit is valid
             */
            if isset this->roleInherits[roleInheritName] {
                let checkRoleToInherits = [];

                for usedRoleToInherit in this->roleInherits[roleInheritName] {
                    array_push(checkRoleToInherits, usedRoleToInherit);
                }

                let usedRoleToInherits = [];

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Use a numeric monotonic column as cursorColumn — typically the auto-increment primary key ('id').
  2. If rows only have UUIDs, add a numeric surrogate column (auto-increment or sequence/bigint) and paginate on that.
  3. If UUID cursors are mandatory, use the offset-based QueryBuilder adapter instead, which does not keyset-compare the column.

Example fix

// before
$paginator = new QueryBuilderCursor(
    [
        'limit'        => 20,
        'builder'      => $builder->orderBy('uuid'),
        'cursorColumn' => 'uuid', // UUIDs are not numeric
    ]
);
$paginator->paginate(); // throws InvalidCursorColumn on page detection

// after
$builder->orderBy('id');
$paginator = new QueryBuilderCursor(
    [
        'limit'        => 20,
        'builder'      => $builder,
        'cursorColumn' => 'id', // numeric auto-increment column
    ]
);
Defensive patterns

Strategy: validation

Validate before calling

// Keyset cursor must be numeric: verify against the model metadata
$metadata = new \Phalcon\Storage\SerializerFactory(); // placeholder
$columnMap = $model->getModelsMetaData()->getDataTypes($model);
$type = $columnMap[$cursorColumn] ?? null;
$numericTypes = [
    \Phalcon\Db\Column::TYPE_INTEGER,
    \Phalcon\Db\Column::TYPE_BIGINTEGER,
    \Phalcon\Db\Column::TYPE_SMALLINTEGER,
    \Phalcon\Db\Column::TYPE_TINYINTEGER,
    \Phalcon\Db\Column::TYPE_MEDIUMINTEGER,
    \Phalcon\Db\Column::TYPE_FLOAT,
    \Phalcon\Db\Column::TYPE_DOUBLE,
];
if ($type === null || !in_array($type, $numericTypes, true)) {
    throw new \InvalidArgumentException(
        "cursorColumn '{$cursorColumn}' must map to a numeric DB column"
    );
}

Type guard

function isNumericCursorValue(mixed $value): bool
{
    return is_numeric($value); // mirrors the adapter's is_numeric() check at paginate()
}

Prevention

When it happens

Trigger: 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.

Common situations: Tables with UUID primary keys; cursor columns chosen as CHAR(36) identifiers; models whose selected column is typecast to string in the resultset.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/e3602d30dae711e7. Report an issue: GitHub.