phalcon/cphalcon · error · Phalcon\Mvc\Model\Exceptions\CannotResolveAttribute

Cannot resolve attribute '{attribute}' in the model '{classN

Error message

Cannot resolve attribute '{attribute}' in the model '{className}'

What it means

Thrown by Model::invokeFinder() (phalcon/Mvc/Model.zep:5103): the suffix of a magic finder cannot be resolved to any attribute of the model. The lookup tries the raw suffix, the lcfirst variant, and the uncamelized variant (e.g. 'FirstName' -> 'first_name') against the reverse column map or data types. The exception class is Phalcon\Mvc\Model\Exceptions\CannotResolveAttribute.

Source

Thrown at phalcon/Mvc/Model.zep:5103

         */
        if isset attributes[extraMethod] {
            let field = extraMethod;
        } else {
            /**
             * Lowercase the first letter of the extra-method
             */
            let extraMethodFirst = lcfirst(extraMethod);

            if isset attributes[extraMethodFirst] {
                let field = extraMethodFirst;
            } else {
                /**
                 * Get the possible real method name
                 */
                let field = uncamelize(extraMethod);

                if unlikely !isset attributes[field] {
                    throw new CannotResolveAttribute(extraMethod, get_called_class());
                }
            }
        }

        /**
         * Check if we have "conditions" and "bind" defined
         */
        fetch value, arguments[0];

        if value !== null {
            let params = [
                 "conditions": "[" . field . "] = ?0",
                 "bind"      : [value]
            ];

        } else {
            let params = [
                 "conditions": "[" . field . "] IS NULL"

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Fix the attribute name in the method call to match a real column (mind snake_case uncamizing: findByFirstName maps to first_name)
  2. Whitelist attribute names when finders are built from user input, then map to an explicit query
  3. If the column was renamed, update the call site or keep an alias in the columnMap

Example fix

// before
$invoice = Invoices::findFirstByCustmerId(7); // CannotResolveAttribute('CustmerId')

// after
$invoice = Invoices::findFirstByCustomerId(7);
// with a column map ['customer_id' => 'custId'] you can also use:
$invoice = Invoices::findFirstByCustId(7);
Defensive patterns

Strategy: type-guard

Validate before calling

$allowed = array_keys($model->getModelsMetaData()->getReverseColumnMap($model) ?: $model->getModelsMetaData()->getDataTypes($model));
$attr = 'custmer_id'; // from user input
if (!in_array($attr, $allowed, true)) {
    // reject before building a finder method name
    throw new InvalidArgumentException("unknown attribute {$attr}");
}
$method = 'findFirstBy' . ucfirst(camelize($attr));

Type guard

function isValidFinderAttribute(string $model, string $attribute): bool
{
    $meta = (new $model)->getModelsMetaData();
    $attrs = $meta->getReverseColumnMap(new $model) ?: $meta->getDataTypes(new $model);
    return isset($attrs[$attribute]) || isset($attrs[lcfirst($attribute)]) || isset($attrs[uncamelize($attribute)]);
}

Try / catch

try {
    $invoice = Invoices::findFirstByCustmerId(7);
} catch (\Phalcon\Mvc\Model\Exceptions\CannotResolveAttribute $e) {
    // attribute name typo: fall back to an explicit query or return not-found
    $invoice = Invoices::findFirst(['customer_id = ?0', 'bind' => [7]]);
}

Prevention

When it happens

Trigger: Calling a finder whose attribute does not exist: Invoices::findFirstByCustmer(1) (typo), findByEmail() when the model/table has no 'email' column, or a finder built from user input where the attribute name is arbitrary.

Common situations: Typos in the magic method name; column renamed in a migration while old finder calls remain; finder names built dynamically from request parameters (also a safety concern); column map renaming that hides the real column name from uncamelize().

Related errors


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