symfony/translation · error · InvalidResourceException

The pgs:switch attribute must not be empty.

Error message

The pgs:switch attribute must not be empty.

What it means

In XLIFF 2.0 files using the pgs (translation provenance/skeleton) extension, the pgs:switch attribute selects which sub-element to use. The loader throws InvalidResourceException when this attribute is present but empty (or whitespace only), because no switch criteria can be derived.

Solutions

  1. Populate the pgs:switch attribute with space-separated type:variable tokens (e.g. "env:BRANCH os:PLATFORM").
  2. Remove the pgs:switch attribute entirely if switching is not needed.
  3. Open the file in the exporting tool and re-export with the extension settings completed.

Example fix

// before
<unit id="u1" pgs:switch="">...</unit>
// after
<unit id="u1" pgs:switch="env:BRANCH">...</unit>
Defensive patterns

Strategy: validation

Validate before calling

$xml = simplexml_load_file($resource);
foreach ($xml->xpath('//*[@pgs:switch]') ?: [] as $el) {
    if ('' === trim((string) $el->attributes('pgs', true)->switch ?? '')) {
        throw new \RuntimeException('Empty pgs:switch in '.$resource);
    }
}

Try / catch

try {
    $catalogue = $loader->load($resource, $locale);
} catch (InvalidResourceException $e) {
    if (str_contains($e->getMessage(), 'pgs:switch attribute must not be empty')) {
        // fix or strip the pgs:switch attribute
    }
    throw $e;
}

Prevention

When it happens

Trigger: Loading an XLIFF 2.0 file whose <unit> (pgs unit) carries pgs:switch="" or pgs:switch=" ", reaching parsePgsSwitch via extractXliff2PgsUnit.

Common situations: Translation tooling that emits the pgs:switch attribute without populating it; hand-edited XLIFF where the variable mapping was deleted.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15). Data as JSON: /api/errors/55b49f9e3e40727d. Report an issue: GitHub.

Appendix: source

Thrown at Loader/XliffFileLoader.php:256

        $metadata = ['pgs-switch' => $pgsSwitch];
        if (isset($unit->notes)) {
            $metadata['notes'] = [];
            foreach ($unit->notes->note as $noteNode) {
                $note = array_map('strval', $noteNode->attributes() ?? []);

                $note['content'] = (string) $noteNode;
                $metadata['notes'][] = $note;
            }
        }

        $catalogue->setMetadata($source, $metadata, $intlDomain);
    }

    private function parsePgsSwitch(string $pgsSwitch): array
    {
        $trimmed = trim($pgsSwitch);
        if ('' === $trimmed) {
            throw new InvalidResourceException('The pgs:switch attribute must not be empty.');
        }

        $switches = [];
        foreach (preg_split('/\s+/', $trimmed) as $item) {
            $parts = explode(':', $item, 2);
            if (2 !== \count($parts) || '' === $parts[0] || '' === $parts[1]) {
                throw new InvalidResourceException(\sprintf('The pgs:switch token "%s" must use the "type:variable" form.', $item));
            }
            $switches[] = ['type' => $parts[0], 'variable' => $parts[1]];
        }

        return $switches;
    }

    private function extractPgsSegmentText(\SimpleXMLElement $element, array $switches): string
    {
        $pluralVariables = [];
        foreach ($switches as $switch) {

View on GitHub (pinned to ae9e8a51bc)