phalcon/cphalcon · error · Phalcon\Mvc\Model\MetaData\Exceptions\NoAnnotationsForClass

No annotations were found in class {className}

Error message

No annotations were found in class {className}

What it means

When the Annotations metadata strategy builds column maps, it asks the 'annotations' service for a Reflection of the model class ($annotations->get($className)) and requires an object back. If the service returns anything non-object — typically a cached annotation entry that deserialized into a scalar (serializer mismatch, entry written by another version) or a custom annotations adapter whose read() returns junk — this exception is thrown with the class name. Note the distinction: a class with no annotations normally yields an empty Reflection and fails later with NoPropertyAnnotationsForClass; this error means no Reflection object came back at all.

Source

Thrown at phalcon/Mvc/Model/MetaData/Strategy/Annotations.zep:43

     */
    final public function getColumnMaps(<ModelInterface> model, <DiInterface> container) -> array
    {
        var annotations, className, reflection, propertiesAnnotations, property,
            propAnnotations, columnAnnotation, columnName;
        array orderedColumnMap, reversedColumnMap;
        bool hasReversedColumn;

        if unlikely typeof container != "object" {
            throw new InvalidContainer();
        }

        let annotations = container->get("annotations");

        let className = get_class(model),
            reflection = annotations->get(className);

        if unlikely typeof reflection != "object" {
            throw new NoAnnotationsForClass(className);
        }

        /**
         * Get the properties defined in
         */
        let propertiesAnnotations = reflection->getPropertiesAnnotations();

        if unlikely empty propertiesAnnotations {
            throw new NoPropertyAnnotationsForClass(className);
        }

        let orderedColumnMap = [],
            reversedColumnMap = [],
            hasReversedColumn = false;

        for property, propAnnotations in propertiesAnnotations {
            /**
             * All columns marked with the 'Column' annotation are considered columns

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Flush the annotations cache backend (delete the class keys / clear APCu) so entries are re-parsed from source.
  2. Verify the 'annotations' DI service resolves to a standard Phalcon annotations adapter and that its serializer matches on every server.
  3. If the model genuinely has no annotations, switch the metadata strategy to Introspection (the default) or annotate the model properties (@Column, @Primary, @Identity).
  4. After serializer or version changes, change the annotations cache prefix so old and new entries never mix.

Example fix

// before: annotations cache poisoned by a serializer change
$di->setShared('annotations', function () {
    return new Phalcon\Annotations\Adapter\Redis(['prefix' => 'annotations']);
});
$strategy->getColumnMaps(new Invoices(), $di); // NoAnnotationsForClass

// after: bump the prefix (or flush) after serializer/version changes
$di->setShared('annotations', function () {
    return new Phalcon\Annotations\Adapter\Redis(['prefix' => 'annotations-v2']);
});
Defensive patterns

Strategy: validation

Validate before calling

$annotations = $container->getShared('annotations');
if (!is_object($annotations->get(Invoices::class))) {
    throw new RuntimeException('Stale annotations cache for ' . Invoices::class . ' - flush the backend');
}

Type guard

function annotationsReflectionIsObject(object $annotations, string $className): bool
{
    return is_object($annotations->get($className));
}

Try / catch

use Phalcon\Mvc\Model\MetaData\Exceptions\NoAnnotationsForClass;

try {
    $maps = $strategy->getColumnMaps($model, $container);
} catch (NoAnnotationsForClass $e) {
    flushAnnotationsBackend(); // delete class-keyed entries
    $maps = $strategy->getColumnMaps($model, $container); // re-parse once
}

Prevention

When it happens

Trigger: Running the Annotations strategy (or custom code calling Annotations::getColumnMaps()) on a model whose class-name key in the annotations cache holds a non-object value; a custom 'annotations' service whose get() can return null/scalars; an annotations backend shared across servers with different serializers or Phalcon versions.

Common situations: Switching annotations adapters (APCu to Redis) while old entries persist under the same class keys; igbinary/serialize mismatch after a PHP or Phalcon upgrade; home-grown annotations adapters that skip parsing and return null on misses.

Related errors


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