phalcon/cphalcon · warning · Phalcon\Acl\Exceptions\CircularInheritanceError
Role '{roleName}' (to inherit) produces an infinite loop
Error message
Role '{roleName}' (to inherit) produces an infinite loop What it means
Queue producers extend Phalcon\Queue\Adapter\AbstractProducer, whose default setDeliveryDelay() treats any non-null argument as unsupported and throws DeliveryDelayNotSupportedException. A null value (the default) is accepted and is a no-op; only requesting an actual delay triggers the throw. Transports that do support delayed delivery override this method.
Source
Thrown at phalcon/Acl/Adapter/Memory.zep:368
* Walk the inheritance queue with an integer cursor instead
* of `array_shift`. New roles enqueued by the body land at
* the end of `checkRoleToInherits`, so advancing `pendingIndex`
* preserves FIFO order without paying `array_shift`'s O(n)
* reindex per pop.
*/
let pendingIndex = 0;
while pendingIndex < count(checkRoleToInherits) {
let checkRoleToInherit = checkRoleToInherits[pendingIndex];
let pendingIndex++;
if isset usedRoleToInherits[checkRoleToInherit] {
continue;
}
let usedRoleToInherits[checkRoleToInherit] = true;
if unlikely roleName == checkRoleToInherit {
throw new CircularInheritanceError(roleInheritName);
}
/**
* Push inherited roles
*/
if isset this->roleInherits[checkRoleToInherit] {
for usedRoleToInherit in this->roleInherits[checkRoleToInherit] {
array_push(checkRoleToInherits, usedRoleToInherit);
}
}
}
}
let this->roleInherits[roleName][] = roleInheritName;
}
return true;
}View on GitHub (pinned to b7419de9cd)
Solutions
- Do not call setDeliveryDelay() on transports without delay support, or call it with null explicitly.
- Check whether your concrete producer class overrides setDeliveryDelay() before relying on the feature.
- If delayed delivery is a hard requirement, switch to a transport that implements it (e.g. an AMQP-based backend).
Example fix
// before
$producer->setDeliveryDelay(5000); // throws on transports without delay support
// after
// only set a delay when the transport advertises support
if (get_class($producer) !== \Phalcon\Queue\Adapter\AbstractProducer::class
&& method_exists($producer, 'setDeliveryDelay')) {
// still guard: the base implementation throws for non-null values
}
// safest: simply omit the call on unsupported transports
$producer->send($queue, $message); Defensive patterns
Strategy: try-catch
Try / catch
try {
$producer->setDeliveryDelay(5000);
} catch (\Phalcon\Queue\Exceptions\DeliveryDelayNotSupportedException $e) {
// transport cannot delay: enqueue now, or choose another transport
$logger->warning('Delay unsupported by this transport; sending immediately');
} Prevention
- Check the concrete producer class: only transports overriding setDeliveryDelay() accept non-null values.
- Keep broker-specific feature calls behind an interface guarded by capability detection.
When it happens
Trigger: $producer->setDeliveryDelay(5000) (or any non-null value) on a producer whose transport inherits the base implementation, e.g. the Beanstalk or Redis queue adapters in this codebase.
Common situations: Writing transport-agnostic code against ProducerInterface that calls all feature setters; porting code from a broker supporting delays (RabbitMQ, SQS) to beanstalk-style transports; feature flags turning delay on globally.
Related errors
- Role must be either a string or implement RoleInterface
- Access '{accessName}' does not exist in component '{componen
- Access '{access}' does not exist in component '{componentNam
- {elementName} '{element}' does not exist in the {suffix}
- Your passed parameter does not have the same class as the pa
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/6ce840d2d7925dd5.
Report an issue: GitHub.