yiisoft/yii2 · error · yii\base\InvalidArgumentException
Attribute name must contain word characters only.
Error message
Attribute name must contain word characters only.
What it means
BaseHtml::getAttributeName() strips the tabular prefix/suffix from an attribute expression using Html::$attributeRegex ('/(^|.*\])([\w\.\+]+)(\[.*|$)/u'); if the expression does not match — i.e. the attribute part contains characters outside word chars, dot, or plus — it throws InvalidArgumentException. Every active* form helper resolves attribute names through this method, so malformed attribute expressions break form rendering.
Source
Thrown at framework/helpers/BaseHtml.php:2274
*
* - `[0]content` is used in tabular data input to represent the "content" attribute
* for the first model in tabular input;
* - `dates[0]` represents the first array element of the "dates" attribute;
* - `[0]dates[0]` represents the first array element of the "dates" attribute
* for the first model in tabular input.
*
* If `$attribute` has neither prefix nor suffix, it will be returned back without change.
* @param string $attribute the attribute name or expression
* @return string the attribute name without prefix and suffix.
* @throws InvalidArgumentException if the attribute name contains non-word characters.
*/
public static function getAttributeName($attribute)
{
if (preg_match(static::$attributeRegex, $attribute, $matches)) {
return $matches[2];
}
throw new InvalidArgumentException('Attribute name must contain word characters only.');
}
/**
* Returns the value of the specified attribute name or expression.
*
* For an attribute expression like `[0]dates[0]`, this method will return the value of `$model->dates[0]`.
* See [[getAttributeName()]] for more details about attribute expression.
*
* If an attribute value is an instance of [[ActiveRecordInterface]] or an array of such instances,
* the primary value(s) of the AR instance(s) will be returned instead.
*
* @param Model $model the model object
* @param string $attribute the attribute name or expression
* @return string|array|null the corresponding attribute value
* @throws InvalidArgumentException if the attribute name contains non-word characters.
*/
public static function getAttributeValue($model, $attribute)
{View on GitHub (pinned to 66f00d18a2)
Solutions
- Sanitize dynamic field names to [A-Za-z0-9_.+] before rendering (e.g. preg_replace('/[^\w\.\+]/', '_', $name)).
- Map external/custom field names to safe model attributes through a lookup table instead of forwarding them raw.
- Pre-test expressions with preg_match(Html::$attributeRegex, $name) and fall back to a safe default for failures.
- Keep virtual attribute names (model methods like getName0) word-char only.
Example fix
// before
echo Html::activeTextInput($model, $dynamicField); // $dynamicField = 'contact e-mail'
// after
$safeName = preg_replace('/[^\w\.\+]/u', '_', $dynamicField);
echo Html::activeTextInput($model, $safeName); Defensive patterns
Strategy: validation
Validate before calling
if (!preg_match(\yii\helpers\Html::$attributeRegex, $attribute)) {
throw new \InvalidArgumentException("Unsafe attribute name for form rendering: {$attribute}");
}
echo \yii\helpers\Html::activeTextInput($model, $attribute); Type guard
/** True when Html can resolve the attribute expression. @param string $attribute */
function isRenderableAttribute(string $attribute): bool
{
return (bool) preg_match(\yii\helpers\Html::$attributeRegex, $attribute);
} Try / catch
try {
$name = \yii\helpers\Html::getAttributeName($attribute);
} catch (\yii\base\InvalidArgumentException $e) {
\Yii::warning("Rejected attribute name '{$attribute}'", 'forms');
$name = preg_replace('/[^\\w\\.\\+]/u', '_', $attribute);
} Prevention
- Whitelist dynamic field names against the model's attributes() / safe attributes list.
- Sanitize external field names to word characters before they reach any active* helper.
- Keep model attribute names word-char only; use labels for display text.
- Cover dynamic form builders with tests feeding hostile names (spaces, dashes, brackets).
When it happens
Trigger: Html::activeTextInput($model, 'full name') (space); attribute 'user-name' (hyphen); '[0]' with no attribute name after it; expressions like '[]'; an empty string; attribute names copied from DB columns containing dashes or spaces and forwarded verbatim.
Common situations: Dynamic form builders (CMS, EAV/meta fields) rendering user-defined field names; API payloads supplying field names; attributes derived from column names like 'first-name'; localization data accidentally used as attribute names.
Related errors
- {class}::formName() cannot be empty for tabular inputs.
- Unknown scenario: $scenario
- Invalid validation rule: a rule must specify both attribute
- Operator '$operator' requires three operands.
- Operator '$operator' requires two operands.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/49facdcc0109b6c8.
Report an issue: GitHub.