phalcon/cphalcon · error · Phalcon\Annotations\Exceptions\CannotReadAnnotationData

Cannot read annotation data

Error message

Cannot read annotation data

What it means

The Annotations Stream adapter caches parsed annotations as serialized Reflection objects on disk. On read, unserialize() runs under a temporary error handler; if unserialize emits any E_WARNING (bad data, wrong offset, truncated payload), the handler sets a flag and the adapter throws CannotReadAnnotationData instead of returning garbage. It means the cache file under annotationsDir exists but its contents cannot be unserialized.

Source

Thrown at phalcon/Annotations/Adapter/Stream.zep:94

        if unlikely empty contents {
            return false;
        }

        globals_set("warning.enable", false);
        set_error_handler(
            function (number, message, file, line) {
                globals_set("warning.enable", true);
            },
            E_WARNING
        );

        let contents = unserialize(contents);

        restore_error_handler();

        if unlikely globals_get("warning.enable") {
            throw new CannotReadAnnotationData();
        }

        return contents;
    }

    /**
     * Writes parsed annotations to files
     */
    public function write( string key, <Reflection> data) -> void
    {
        var code;
        string path;

        /**
         * Paths must be normalized before be used as keys
         */
        let path = this->annotationsDir . prepare_virtual_path(key, "_") . ".php",
            code = serialize(data);

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Delete everything under the configured annotationsDir so annotations are re-parsed and re-cached on the next request
  2. If it recurs, check the directory for concurrent writers and give each deployment its own cache prefix/directory
  3. Verify the annotationsDir is writable and not subject to open_basedir restrictions that could corrupt write behavior
  4. As a stopgap, switch to the Memory adapter (no disk cache) while you fix the underlying serialization issue

Example fix

// before: stale/corrupt cache triggers CannotReadAnnotationData on first get()
$annotations = new \Phalcon\Annotations\Adapter\Stream(['annotationsDir' => '/app/storage/annotations/']);
$reflector = $annotations->get(Invoices::class);
// after: purge the cache once after upgrading, then use normally
foreach (glob('/app/storage/annotations/*.php') ?: [] as $file) {
    unlink($file);
}
$reflector = $annotations->get(Invoices::class);
Defensive patterns

Strategy: fallback

Try / catch

try {
    $reflector = $annotations->get(Invoices::class);
} catch (\Phalcon\Annotations\Exceptions\CannotReadAnnotationData $e) {
    // cache entry corrupt: purge and regenerate once, then retry
    array_map('unlink', glob($annotationsDir . '*.php') ?: []);
    $reflector = $annotations->get(Invoices::class);
}

Prevention

When it happens

Trigger: `$annotations->get($class)` / `$annotations->read($key)` on a class whose cached file in annotationsDir is corrupt or incompatible: truncated writes (disk full, killed process), cache files produced by an older Phalcon/PHP release, or files edited by hand.

Common situations: Deploying a new Phalcon version over old cache files; concurrent workers writing the same cache key; a disk-full event truncating serialized payloads; copying caches between environments built by different PHP versions.

Related errors


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