Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get Error: Command failed with exit code 2: while also getting back the expected stdout #515

Closed
ctf0 opened this issue Dec 28, 2022 · 10 comments

Comments

@ctf0
Copy link

ctf0 commented Dec 28, 2022

am trying to use execa with ripgrep, however for some reason am getting both the error & data as an error

const filesNamesRg = 'Kernel|Handler'
const rgExcludeDirs = 'vendor,stubs'

const { stdout } = await execa('rg', [
    `'((\\\\*\\w+\\\\+)+(${filesNamesRg}))'`,
    '--mmap',
    '--follow',
    '--no-messages',
    '--smart-case',
    '--only-matching',
    "--glob='!*blade.php'",
    `--glob='!{${rgExcludeDirs}}'`,
    "--glob='**/*.php'",
    "./", // https://github.com/BurntSushi/ripgrep/issues/2056#issuecomment-966306579
], {
    cwd   : '/some/path',
    shell : true, // without shell no results are returned, only error
});

console.log(stdout);

-error

Error: Command failed with exit code 2: rg '((\\*\w+\\+)+(Kernel|Handler))' --mmap --follow --no-messages --smart-case --only-matching --glob='!*blade.php' --glob='!{vendor,stubs}' --glob='**/*.php' ./
./routes/web/profile.php:App\Http\Controllers\Auth\UserProfileController
./tests/Feature/Auth/PasswordConfirmationTest.php:Tests\TestCase
./tests/Feature/Auth/PasswordConfirmationTest.php:App\Models\User
// ...

any help how to fix this is appreciated.

@ehmicky
Copy link
Collaborator

ehmicky commented Dec 28, 2022

Hi @ctf0,

What happens if you replace the execa() call with child_process.execFile() instead?

import { execFile } from 'node:child_process'
import { promisify } from 'node:util'

const pExecFile = promisify(execFile);

const filesNamesRg = 'Kernel|Handler'
const rgExcludeDirs = 'vendor,stubs'

const { stdout } = await pExecFile('rg', [
    `'((\\\\*\\w+\\\\+)+(${filesNamesRg}))'`,
    '--mmap',
    '--follow',
    '--no-messages',
    '--smart-case',
    '--only-matching',
    "--glob='!*blade.php'",
    `--glob='!{${rgExcludeDirs}}'`,
    "--glob='**/*.php'",
    "./", // https://github.com/BurntSushi/ripgrep/issues/2056#issuecomment-966306579
], {
    cwd   : '/some/path',
    shell : true, // without shell no results are returned, only error
});

console.log(stdout);

@ctf0
Copy link
Author

ctf0 commented Dec 28, 2022

Error: Command failed: rg '((\\*\w+\\+)+(...
at ChildProcess.exithandler (node:child_process:408:12)
at ChildProcess.emit (node:events:526:28)
at maybeClose (node:internal/child_process:1092:16)
at Socket.<anonymous> (node:internal/child_process:451:11)
at Socket.emit (node:events:526:28)
at Pipe.<anonymous> (node:net:687:12)
at Pipe.callbackTrampoline (node:internal/async_hooks:130:17

same error with/without shell

@ehmicky
Copy link
Collaborator

ehmicky commented Dec 28, 2022

Is this the same error as when using Execa?

@ctf0
Copy link
Author

ctf0 commented Dec 28, 2022

no, different

@ehmicky
Copy link
Collaborator

ehmicky commented Dec 28, 2022

@ctf0 Could you please elaborate and give additional details so we can better help you?

In particular, the error message looks the same to me (or more precisely have non-significant small differences) whether Execa is used or not.

I am unable to reproduce your setup since it seems to rely on specific files being present locally when the command is executed.

More importantly, I am not clear about whether your problem is that:

  1. The command fails (with exit code 2)? If so, this behavior does not seem to be different with/without Execa.
  2. The command fails but also has some stdout? That, in itself, is not a problem: commands can fail and still print on stdout.
  3. The command's behavior changes depending on whether shell is used or not? This is also rather expected for many commands.

@ctf0
Copy link
Author

ctf0 commented Dec 28, 2022

I am unable to reproduce your setup since it seems to rely on specific files being present locally when the command is executed.

np, the steps are

  1. install ripgrep
  2. prepare some files that might have some of the words we will be looking for
  3. use the same command setup as in the main comment & try directly through trmnl to confirm that the command is actually working, then try again with execa

The command fails (with exit code 2)? If so, this behavior does not seem to be different with/without Execa.

not exactly, because with execa i have this error + output, without execa i have a different error, true that both doesnt give much of meaning to debug but thier differences prove something.

The command fails but also has some stdout? That, in itself, is not a problem: commands can fail and still print on stdout.

great, how can we only get the output without the error ?, if we can view them then thier must be a way to extract them

The command's behavior changes depending on whether shell is used or not? This is also rather expected for many commands.

but cant we understand the exact reason why with the options it works & without it it doesnt, at least in the main example with execa.

if there is a way i can debug this on my part, plz tell me how.

aside from that, does the size of the arg change the behavior ? for example lets say the const filesNamesRg is a group of 20 words joined with a pipe, does the node spawn args have a character limit ? and if so, is there away to get around that ?
i've searched but sadly couldnt find an answer.

@ehmicky
Copy link
Collaborator

ehmicky commented Dec 28, 2022

Thanks for the information @ctf0.

I am sorry but, based on this, I am afraid those questions do not seem to be specifically related to Execa, but with child process execution in general.
I will close this issue. However I am tagging @sindresorhus in case he feels differently about it.

Sorry again for not being able to help you for this matter @ctf0.

@ehmicky ehmicky closed this as completed Dec 28, 2022
@ctf0
Copy link
Author

ctf0 commented Dec 28, 2022

i focken found iiiiiiiiiiiiiit.

first check https://github.com/nodejs/node-v0.x-archive/blob/master/doc/api/process.markdown#exit-codes for codes description "i think this should be part of the reject error instead of just a number" Duck u node

anyway error code 2 is

2 - Unused (reserved by Bash for builtin misuse)

so as the error says, it seems that the command have something that shell/bash thinks is a builtin option & after doing some reading it seems that --follow was the issue 😡 , once removed all was good.

so the final usage should be

const filesNamesRg = 'Kernel|Handler'
const rgExcludeDirs = 'vendor,stubs'

const { stdout } = await execa('rg', [
    `'((\\\\*\\w+\\\\+)+(${filesNamesRg}))'`,
    '--mmap',
    '--no-messages',
    '--smart-case',
    '--only-matching',
    "--glob='!*blade.php'",
    `--glob='!{${rgExcludeDirs}}'`,
    "--glob='**/*.php'",
    "./", // removing this wont resolve anything
], {
    cwd   : '/some/path',
    shell : true, // removing this will give error code 1 instead
});

console.log(stdout);

@ehmicky
Copy link
Collaborator

ehmicky commented Dec 28, 2022

Thanks @ctf0 for confirming the problem was with ripgrep's usage. I had a hunch this was the problem too, but I was unable to confirm this without digging too deep into it.

@ctf0
Copy link
Author

ctf0 commented Dec 28, 2022

not exactly, because if we ran the command in a trmnl it will work, also the argument comes after the command in the spawn items order,
surely u r more experienced in this than me but i believe this is more of an issue with node than ripgrep & might happen again with any other pkgs with similar options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants