symfony/translation · error · InvalidArgumentException
The writer class " " does not implement the "getFormats()"…
Error message
The writer class "%s" does not implement the "getFormats()" method.
What it means
TranslationExtractCommand requires the injected writer object to expose getFormats() so it can list supported formats for command options. The constructor checks method_exists($writer, 'getFormats') and throws InvalidArgumentException if the check fails.
Solutions
- Add a public static getFormats(): array method to your custom writer class
- Inject the correct TranslationWriter service instead of another object
- Update the custom writer to match the expected interface
Example fix
// before
class MyWriter { public function write(MessageCatalogue $c, string $f, array $o = []): void {} }
// after
class MyWriter {
public function write(MessageCatalogue $c, string $f, array $o = []): void {}
public static function getFormats(): array { return ['custom']; }
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!method_exists($writer, 'getFormats')) {
throw new \InvalidArgumentException('Writer must implement getFormats()');
} Type guard
function isCompatibleWriter(object $writer): bool {
return method_exists($writer, 'getFormats');
} Try / catch
try {
$command = new TranslationExtractCommand($writer, $loader, $enabledLocales);
} catch (\InvalidArgumentException $e) {
// inspect injected writer class
throw new \LogicException('Invalid writer injected: '.get_debug_type($writer));
} Prevention
- Make custom writers implement a common interface including getFormats()
- Add a static analysis test asserting writer compatibility
- Check DI service wiring when constructing the command
When it happens
Trigger: Constructing TranslationExtractCommand with an object (e.g. a custom TranslationWriterInterface implementation or a mock) that lacks a public getFormats() method; passing the wrong variable to the constructor.
Common situations: Custom writer implementations missing the method; wiring errors in Symfony DI where the wrong service is injected; outdated custom writers after upgrading symfony/translation.
Related errors
- Loading translations from the Xliff format requires the…
- This is not a local file
- File " " not found.
- This is neither a file nor an XLIFF string
- Unable to load
AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15).
Data as JSON: /api/errors/e2f105e3b3ac88e7.
Report an issue: GitHub.
Appendix: source
Thrown at Command/TranslationExtractCommand.php:71
* @param \Closure():KernelInterface|KernelInterface $kernel
*/
public function __construct(
private \Closure|KernelInterface $kernel,
private TranslationWriterInterface $writer,
private TranslationReaderInterface $reader,
private ExtractorInterface $extractor,
private string $defaultLocale,
private ?string $defaultTransPath = null,
private ?string $defaultViewsPath = null,
private array $transPaths = [],
private array $codePaths = [],
private array $enabledLocales = [],
) {
$this->enabledLocales = array_filter($enabledLocales);
parent::__construct();
if (!method_exists($writer, 'getFormats')) {
throw new \InvalidArgumentException(\sprintf('The writer class "%s" does not implement the "getFormats()" method.', $writer::class));
}
}
protected function configure(): void
{
$this
->setDefinition([
new InputArgument('locale', InputArgument::REQUIRED, 'The locale'),
new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'),
new InputOption('prefix', null, InputOption::VALUE_REQUIRED, 'Override the default prefix', '__'),
new InputOption('no-fill', null, InputOption::VALUE_NONE, 'Extract translation keys without filling in values'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Override the default output format', 'xlf12'),
new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'),
new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'),
new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'),
new InputOption('domain', null, InputOption::VALUE_REQUIRED, 'Specify the domain to extract'),
new InputOption('sort', null, InputOption::VALUE_REQUIRED, 'Return list of messages sorted alphabetically'),
new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'),View on GitHub (pinned to ae9e8a51bc)