phalcon/cphalcon · error · Phalcon\Tag\Exception

Value at index: '{key}' type: '{type}' cannot be rendered

Error message

Value at index: '{key}' type: '{type}' cannot be rendered

What it means

When Phalcon\Tag renders an attribute list, every string key with a non-null value becomes a key="value" pair. PHP arrays and resources have no meaningful string form, so an attribute value of either type throws Phalcon\Tag\Exception ("Value at index: '{key}' type: '{type}' cannot be rendered"), with {type} from gettype(). Only these two types are rejected — scalars pass (objects survive if they stringify during concatenation).

Source

Thrown at phalcon/Tag.zep:1004

            }
        }

        for key, value in attributes {
            if !isset attrs[key] {
                let attrs[key] = value;
            }
        }

        let escaper = <EscaperInterface> self::getEscaper(attributes);

        unset attrs["escape"];

        let attrParts = [];

        for key, value in attrs {
            if typeof key == "string" && value !== null {
                if unlikely (typeof value == "array" || typeof value == "resource") {
                    throw new Exception(
                        "Value at index: '" . key . "' type: '" . gettype(value) . "' cannot be rendered"
                    );
                }

                if escaper {
                    let escaped = escaper->attributes(value);
                } else {
                    let escaped = value;
                }

                let attrParts[] = key . "=\"" . escaped . "\"";
            }
        }

        if empty attrParts {
            return code;
        }

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Flatten list attributes yourself: 'class' => implode(' ', $classes)
  2. Filter out resource values before rendering
  3. Map domain data to an explicit scalar-only attribute whitelist instead of passing raw arrays

Example fix

// before
echo \Phalcon\Tag::textField(['name' => 'email', 'class' => ['form-control', 'w-100']]);

// after
echo \Phalcon\Tag::textField([
    'name'  => 'email',
    'class' => implode(' ', ['form-control', 'w-100']),
]);
Defensive patterns

Strategy: validation

Validate before calling

$attributes = array_filter($attributes, function ($value) {
    return !is_resource($value);
});

$attributes = array_map(function ($value) {
    return is_array($value) ? implode(' ', $value) : $value;
}, $attributes);

echo \Phalcon\Tag::textField($attributes);

Type guard

function isRenderableAttributeValue($value): bool
{
    return null === $value || (!is_array($value) && !is_resource($value));
}

Prevention

When it happens

Trigger: Tag::textField(['name' => 'email', 'class' => ['form-control', 'w-100']]) — array attribute; a file/stream handle ending up in an attribute array; merging structured domain data into params so extra keys become attributes.

Common situations: Building 'class' or 'data-*' attributes as arrays out of convenience; passing whole config/request arrays as tag params expecting unknown keys to be ignored.

Related errors


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