{"record":{"id":"a5797a22ef82e6f3","repo":"twigphp/Twig","slug":"only-empty-strings-may-be-passed-as-string-arguments-to-html","errorCode":null,"errorMessage":"Only empty strings may be passed as string arguments to html_attr_merge. This is to support the implicit else clause for ternary operators.","messagePattern":"Only empty strings may be passed as string arguments to html_attr_merge\\. This is to support the implicit else clause for ternary operators\\.","errorType":"exception","errorClass":"Twig\\Error\\RuntimeError","httpStatus":null,"severity":"error","filePath":"extra/html-extra/HtmlExtension.php","lineNumber":160,"sourceCode":"            'sst' => new SeparatedTokenList($value, ' '),\n            'cst' => new SeparatedTokenList($value, ', '),\n            'style' => new InlineStyle($value),\n            default => throw new RuntimeError(\\sprintf('Unknown attribute type \"%s\" The only supported types are \"sst\", \"cst\" and \"style\".', $type)),\n        };\n    }\n\n    /** @internal */\n    public static function htmlAttrMerge(iterable|string|false|null ...$arrays): array\n    {\n        $result = [];\n\n        foreach ($arrays as $array) {\n            if (!$array) {\n                continue;\n            }\n\n            if (\\is_string($array)) {\n                throw new RuntimeError('Only empty strings may be passed as string arguments to html_attr_merge. This is to support the implicit else clause for ternary operators.');\n            }\n\n            foreach ($array as $key => $value) {\n                if (!isset($result[$key])) {\n                    $result[$key] = $value;\n\n                    continue;\n                }\n\n                $existing = $result[$key];\n\n                switch (true) {\n                    case $value instanceof MergeableInterface:\n                        $result[$key] = $value->mergeInto($existing);\n                        break;\n                    case $existing instanceof MergeableInterface:\n                        $result[$key] = $existing->appendFrom($value);\n                        break;","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/extra/html-extra/HtmlExtension.php#L142-L178","documentation":"html_attr_merge() merges attribute arrays but forbids non-empty string arguments. Empty strings are allowed only to support Twig's implicit ternary else clause (cond ? attrs : ''); any other string would be ambiguous and is rejected.","triggerScenarios":"Calling twig_html_attr_merge() with a non-empty string argument, e.g. merging an array with 'foo=bar' instead of ['foo' => 'bar'].","commonSituations":"Trying to merge a raw attribute string with an array; a ternary branch accidentally returning a string instead of an array; passing query-string-like text expecting it to be parsed.","solutions":["Convert the string to an associative array first, e.g. ['class' => 'foo'].","Only pass '' (empty string) or arrays/false/null to the merge.","Check each merge operand is_array($x) || '' === $x || null === $x || false === $x before calling."],"exampleFix":"// before\nhtml_attr_merge(['class' => 'a'], 'id=main')\n// after\nhtml_attr_merge(['class' => 'a'], ['id' => 'main'])","handlingStrategy":"validation","validationCode":"foreach ($operands as $op) { if (!is_array($op) && '' !== $op && null !== $op && false !== $op) throw new \\TypeError('html_attr_merge operands must be arrays or empty strings'); }","typeGuard":"function isMergeOperand(mixed $v): bool { return is_array($v) || '' === $v || null === $v || false === $v; }","tryCatchPattern":"try { $attrs = html_attr_merge($base, $extra); } catch (Twig\\Error\\RuntimeError $e) { $attrs = $base; }","preventionTips":["Never pass raw attribute strings; always build arrays","Remember '' is only valid as a ternary else placeholder","Normalize operands with array_map cast helpers"],"tags":["twig","type-error","html-attr"],"backgroundTag":"invalid-argument-value","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}