Skip to content

Section failures discard the underlying exception, so the cause is unrecoverable #55

Description

@GALPR

Full disclosure: Evidence gathering and issue writing was done with the help of Claude Code

Version: Symfony Language Tools 0.17.1

Summary

When a runtime metadata section fails, the only text produced anywhere is the section name in a
fixed sentence. The throwable — class, message, file, line — is dropped at the catch site and
never recorded, logged or displayed.

SymfonyLspBridgeContext::addError() accepts only the section name, so there is no parameter a
cause could be passed in (bridge/context.php:473):

public function addError(string $section): void
{
    $this->errors[] = [
        'section' => $section,
        'message' => sprintf('Unable to load the "%s" runtime metadata section.', $section),
    ];
}

and every catch site discards the throwable by not binding it (bridge.php:138, and identically
in sections/twig.php:39, sections/security.php:23, sections/container.php:8,
sections/routes.php:8, …):

} catch (Throwable) {
    $context->addError($sectionName);
}

Reproduction

Make one section fail with a distinctive message — a Twig extension that throws when the
section's debug:twig runs:

public function getFunctions(): array
{
    throw new \RuntimeException('deliberate twig section failure');
}

deliberate twig section failure then appears nowhere: not in the bridge payload, not on its
stderr (empty), not in any output the tooling produces. All that is reported is:

Unable to load the "twig" runtime metadata section.

Why it matters

A section failing inside an otherwise successful run is the common case, because the bridge exits
0 when that happens — so the situation users are most likely to hit produces the least
information.

Diagnosing our own case meant patching the extracted bridge to print the throwable and re-running
it by hand; the cause was several frames deep and not guessable from the section name. Anyone
whose project trips a section faces the same reverse-engineering to learn whether the problem is
their code, their configuration, or the tool.

Expected

Record the throwable's class and message, ideally the first frames too, and surface them wherever
the failure is reported. If project output must stay out of the log by default, an opt-in flag or
a dedicated channel would still make diagnosis possible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions