{"record":{"id":"bfddd9c1fbee3c4a","repo":"twigphp/Twig","slug":"s-getoperators-must-return-an-array-with-operators-got-s","errorCode":null,"errorMessage":"\"%s::getOperators()\" must return an array with operators, got \"%s\".","messagePattern":"\"(.+?)::getOperators\\(\\)\" must return an array with operators, got \"(.+?)\"\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/ExtensionSet.php","lineNumber":509,"sourceCode":"                throw new \\LogicException('getTokenParsers() must return an array of \\Twig\\TokenParser\\TokenParserInterface.');\n            }\n\n            $this->parsers[$parser->getTag()] = $parser;\n        }\n\n        // node visitors\n        foreach ($extension->getNodeVisitors() as $visitor) {\n            $this->visitors[] = $visitor;\n        }\n\n        // expression parsers\n        if (method_exists($extension, 'getExpressionParsers')) {\n            $this->expressionParsers->add($extension->getExpressionParsers());\n        }\n\n        $operators = $extension->getOperators();\n        if (!\\is_array($operators)) {\n            throw new \\InvalidArgumentException(\\sprintf('\"%s::getOperators()\" must return an array with operators, got \"%s\".', $extension::class, get_debug_type($operators).(\\is_resource($operators) ? '' : '#'.$operators)));\n        }\n\n        if (2 !== \\count($operators)) {\n            throw new \\InvalidArgumentException(\\sprintf('\"%s::getOperators()\" must return an array of 2 elements, got %d.', $extension::class, \\count($operators)));\n        }\n\n        $expressionParsers = [];\n        foreach ($operators[0] as $operator => $op) {\n            $expressionParsers[] = new UnaryOperatorExpressionParser($op['class'], $operator, $op['precedence'], $op['precedence_change'] ?? null, '', $op['aliases'] ?? []);\n        }\n        foreach ($operators[1] as $operator => $op) {\n            $op['associativity'] = match ($op['associativity']) {\n                1 => InfixAssociativity::Left,\n                2 => InfixAssociativity::Right,\n                default => throw new \\InvalidArgumentException(\\sprintf('Invalid associativity \"%s\" for operator \"%s\".', $op['associativity'], $operator)),\n            };\n\n            if (isset($op['callable'])) {","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/ExtensionSet.php#L491-L527","documentation":"During extension initialization Twig calls getOperators() and requires an array; this InvalidArgumentException means a non-array was returned. getOperators() must return an array of exactly two elements: [unaryOperators, binaryOperators]. The message includes the actual debug type (and value for scalars) to pinpoint the bad return.","triggerScenarios":"An extension's getOperators() returns null, false, a string, a Generator, or any non-array — e.g. returning the result of a helper that failed, returning a single merged operator array as an object, or an override without a return-type declaration silently returning null.","commonSituations":"Legacy extensions written for very old Twig APIs; hand-written extensions returning a single operator array instead of [unary, binary]; misconfigured third-party extensions after a Twig upgrade; overridden getOperators() with a code path that falls through without returning.","solutions":["Make getOperators() return exactly two arrays: return [$unaryOperators, $binaryOperators];","Add an explicit array return type (public function getOperators(): array) so PHP rejects null/non-array returns early.","Inspect what the extension actually returns (get_debug_type) and fix the offending return statement.","Remove or upgrade the offending third-party extension to a version compatible with your Twig."],"exampleFix":"// before\nclass MyExtension extends AbstractExtension {\n    public function getOperators() { return ['~' => [...]]; } // flat map, not 2-element array\n}\n\n// after\nclass MyExtension extends AbstractExtension {\n    public function getOperators(): array {\n        return [\n            ['not' => ['precedence' => 50, 'class' => \\Twig\\Node\\Expression\\Unary\\NotUnary::class]],\n            ['~' => ['precedence' => 30, 'class' => \\Twig\\Node\\Expression\\Binary\\ConcatBinary::class]],\n        ];\n    }\n}","handlingStrategy":"validation","validationCode":"$ops = $ext->getOperators();\nif (!\\is_array($ops)) {\n    throw new \\UnexpectedValueException(get_class($ext).'::getOperators() must return [unary, binary] arrays, got '.get_debug_type($ops));\n}","typeGuard":"function isArrayOperators(mixed $ops): bool {\n    return \\is_array($ops);\n}","tryCatchPattern":"try {\n    $twig->addExtension($ext);\n    $twig->loadTemplate('any.twig');\n} catch (\\InvalidArgumentException $e) {\n    if (str_contains($e->getMessage(), '::getOperators()')) {\n        // inspect and fix the extension's getOperators() return value\n    }\n    throw $e;\n}","preventionTips":["Return exactly [unaryOperators, binaryOperators] from getOperators()","Add an explicit array return type: public function getOperators(): array","Test extension initialization in CI so a bad getOperators() is caught before production","Verify third-party extension compatibility with your Twig major version before upgrading"],"tags":["php","twig","extensions","type-validation"],"backgroundTag":"config-type-mismatch","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"}