Problem/Motivation
A low level failure trying to run a Composer command in \Drupal\package_manager\Validator\ComposerExecutableValidator::validateStagePreOperation will throw an error that "Update readiness check" displays on the Status page with the message about configuring the path to Composer--which has nothing to do with it. Example:
The process has been signaled with signal "9". See the help page for information on how to configure the path to Composer.
Steps to reproduce
The exact cause of the failure when this issue was discovered has not yet been identified. However, it can be simulated by throwing a \PhpTuf\ComposerStager\Domain\Exception\RuntimeException from \Drupal\package_manager\Validator\ComposerExecutableValidator::runCommand--which seems to be the locus of the problem.
Proposed resolution
Identify the absence of Composer using \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface before even trying to run Composer commands, rather than trying to run one and then trying to distinguish between failure conditions.
Remaining tasks
Issue fork automatic_updates-3320836
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
tedbowComment #3
wim leersThis seems like very important hardening that would make AU more reliable overall. Tempted to put it in #3319030: Drupal Core Roadmap for Package Manager and Update Manager under , but it seems rare/edge case-y enough that it's not worth listing there.
I do worry that we need this nonetheless to be confident that doing this at a later time won't trigger API changes though?
Comment #4
traviscarden commentedComment #5
yash.rode commentedComment #7
yash.rode commentedTried reproducing it, is this the expected behaviour?

Comment #8
yash.rode commentedComment #9
wim leers#7: Almost. You threw a
\RuntimeException, but @TravisCarden said in the issue summary it's a\PhpTuf\ComposerStager\Domain\Exception\RuntimeException. Subtle but important difference! 🤓Comment #10
yash.rode commentedI will get
on using
\PhpTuf\ComposerStager\Domain\Exception\RuntimeExceptionComment #11
wim leersWell that seems sensible/plausible because it's a
PhpTuf\ComposerStager\Domain\Exception\IOException.Assigning to @TravisCarden to clarify and review. He's the maintainer of that package, so he'll know 😊
Comment #12
traviscarden commentedWell, the answer the question exactly as you asked it is that you would need to catch
\PhpTuf\ComposerStager\Domain\Exception\LogicException. (See ComposerRunnerInterface::run.) But that doesn't get us all the way there, because other conditions can also throw that exception, and it's impossible to reliably tell the difference between them. (The other known one is ifproc_open()is unavailable, a requirement peculiar to Symfony Process.)Having through more about it, I propose a different approach: rather than trying to run a Composer command and then identify exactly what went wrong, let's just test for our special case first and handle it cleanly. Just use
\PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface::isFulfilled(). I've updated the issue summary with my new proposed resolution.Comment #13
yash.rode commentedComment #14
yash.rode commentedComment #15
tedbowComment #16
traviscarden commentedBack to you, @Wim Leers!
Comment #17
wim leersThere are 2 nits that should still be applied, but for some reason I can't apply them even though I have push access to https://git.drupalcode.org/project/automatic_updates/-/merge_requests/616 😬
Still: RTBC!
Comment #18
traviscarden commentedI was able to commit the nits, @Wim Leers. It's ready to go.
Comment #19
wim leers🚢
Comment #20
tedbowGoing to commit this as is. But I have 1 question about a possible follow-up in an MR comment
Comment #22
tedbowthanks all!
Comment #23
tedbow