{"record":{"id":"0d34ee881d02f231","repo":"symfony/symfony","slug":"the-marshaller-attribute-of-the-cache-pool-tag","errorCode":null,"errorMessage":"The \"marshaller\" attribute of the \"cache.pool\" tag for service \"%s\" is not supported by chained adapter \"%s\".","messagePattern":"The \"marshaller\" attribute of the \"cache\\.pool\" tag for service \"(.+?)\" is not supported by chained adapter \"(.+?)\"\\.","errorType":"exception","errorClass":"Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php","lineNumber":145,"sourceCode":"                        $chainedPool->replaceArgument($i++, $tags[0]['namespace']);\n                    }\n\n                    if (isset($tags[0]['default_lifetime'])) {\n                        $defaultLifetime = $tags[0]['default_lifetime'];\n\n                        if (!is_numeric($defaultLifetime)) {\n                            $defaultLifetime = (new Definition('int', [$defaultLifetime]))\n                                ->setFactory([ParameterNormalizer::class, 'normalizeDuration']);\n                        }\n\n                        $chainedPool->replaceArgument($i++, $defaultLifetime);\n                    }\n\n                    if (null !== $marshallerServiceId) {\n                        if (null !== $marshallerIndex = $this->findDefaultMarshallerArgumentIndex($adapter)) {\n                            $chainedPool->replaceArgument($marshallerIndex, new Reference($marshallerServiceId));\n                        } elseif (!\\in_array($chainedClass, [ArrayAdapter::class, NullAdapter::class], true)) {\n                            throw new InvalidArgumentException(\\sprintf('The \"marshaller\" attribute of the \"cache.pool\" tag for service \"%s\" is not supported by chained adapter \"%s\".', $id, $chainedClass));\n                        }\n                    }\n\n                    $adapters[] = $chainedPool;\n                }\n\n                $pool->replaceArgument(0, $adapters);\n                unset($tags[0]['provider'], $tags[0]['namespace']);\n                $i = 1;\n            } else {\n                $i = 0;\n            }\n\n            foreach ($attributes as $attr) {\n                if (!isset($tags[0][$attr])) {\n                    // no-op\n                } elseif ('reset' === $attr) {\n                    if ($tags[0][$attr]) {","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/symfony/symfony/blob/698e28026c22cf35d032cdb6e800db48b1535790/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php#L127-L163","documentation":"CachePoolPass supports a 'marshaller' attribute on the cache.pool tag to inject a custom serializer (e.g. for igbinary or encrypted marshalling). For chained adapters, the marshaller is injected into each constituent adapter. If a chained adapter does not wire 'cache.default_marshaller' in its constructor arguments (meaning it has no marshaller slot) and it is not ArrayAdapter or NullAdapter (which legitimately don't need one), the pass cannot inject the marshaller and throws an InvalidArgumentException at compile time.","triggerScenarios":"Tagging a ChainAdapter-based pool with { marshaller: 'my.marshaller' } when one of the chained adapters is a custom adapter class whose definition does not accept cache.default_marshaller as a constructor argument.","commonSituations":"Using a custom adapter class in a chain that doesn't follow the standard Symfony adapter constructor signature, or removing the marshaller argument from a stock adapter definition override.","solutions":["Remove the 'marshaller' attribute from the cache.pool tag for this service.","Ensure each chained adapter's service definition wires 'cache.default_marshaller' as a constructor argument (check findDefaultMarshallerArgumentIndex logic).","Use only built-in adapters (RedisAdapter, PdoAdapter, etc.) in the chain, which already wire the marshaller argument.","Add cache.default_marshaller as a constructor argument to your custom adapter definition."],"exampleFix":"// before\nmy_custom_adapter:\n    class: App\\Cache\\MyCustomAdapter\n    arguments: ['%dsn%']\n    tags:\n        - { name: cache.pool, marshaller: my.marshaller }\n\n// after — wire the marshaller argument\nmy_custom_adapter:\n    class: App\\Cache\\MyCustomAdapter\n    arguments: ['%dsn%', '@cache.default_marshaller']\n    tags:\n        - { name: cache.pool, marshaller: my.marshaller }","handlingStrategy":"validation","validationCode":"// In services.yaml: ensure chained adapters wire cache.default_marshaller\n# my.adapter:\n#     arguments: ['%dsn%', '@cache.default_marshaller']\n# Only then add: tags: [{ name: cache.pool, marshaller: my.marshaller }]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure every adapter in a chain accepts cache.default_marshaller as a constructor argument.","Use stock Symfony adapters in chains; they already wire the marshaller.","Remove the marshaller attribute if using ArrayAdapter/NullAdapter in a chain."],"tags":["cache","di","configuration","compile-time","marshaller","chain-adapter"],"analyzedSha":"698e28026c22cf35d032cdb6e800db48b1535790","analyzedAt":"2026-08-06T23:40:49.025Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}