Why am I getting different behaviour between using stockfish as a child node process and a CLI called process? Copied this question from stackoverflow. Not 100% sure it belongs here but we'll see...

I am building a web interface for the stockfish chess engine using Node, and I noticed that the behaviour of the exact same commands behaves differently.

Here are the UCI commands I use when calling stockfish from the command line:

position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
go movetime 15000


The engine then responds as expected: Does analysis for 15 seconds while outputting every step on stdout, and ends with a suggestion in the following format:

bestmove e2e4 ponder e7e6


Here is the code that makes the same call as a node js child process:

app.get('/next_move/:fen', (req, res) =&gt; {
    const stockfish = spawn('bin/stockfish');
    stockfish.stdin.write(`position fen ${req.params.fen}\ngo movetime 15000`);
    console.info(`Sending UCI command to stockfish: position fen ${req.params.fen}\ngo movetime 15000`);
    stockfish.stdin.end();

    stockfish.stdout.on('error', (error)=&gt;{
        console.error(`${error}`);
        res.status(500).send('Internal server error');
        stockfish.kill();
    });

    stockfish.stdout.on('message', (data)=&gt;{
        console.log(`Message: ${data}`);
    });

    stockfish.stdout.on('data', (data) =&gt;{
        let output = data.toString();
        // Ignore the first line in stdout
        if (output.substring(0, 9) === 'Stockfish') {
            return;
        }
        console.info(`Stockfish output: ${output}`);
        if (output.substring(0, 8) === 'bestmove') {
            res.json({'bestMove': output.substring(8).trim()});
        } else {
            res.status(400).send('Bad FEN string');
        }
        stockfish.kill();
    });
});


After I make this code run via web, get a result almost instantly, and also get a different output from stockfish:

bestmove a2a3


Why is this happening? Is this related to Nodejs or to Stockfish?
It was me who suggested you to come here because you'd need to understand what's happening. The guys on Stackoverflow wouldn't have the knolwedge to answer you.

Firstly, this is definitely your fault since Stockfish wouldn't give you a2a3 unless you have screwed up something. But why a2a3? That's because Stockfish always try to move a pawn before anything else. The way how the bitboard is encoded, it'd start its search from a1 to h1, then a2 to h2, a3 to h3 etc. The a2 white pawn is the first pawn it sees, so it tries to move it.

Now we've established it's your fault, however, it's not possible for us to determine the cause because we don't have your source code. But I can give you some hints, you'll need to experiment yourself.


You have killed the standard input too early. I don't quite understand why you would do stockfish.stdin.end();. Stockfish assumes the standard input/output works, always works.
You have failed to setup the bitboard. I'm confident you'd get the error unless you let Stockfish to setup it's internal data structure. Have you done it? The code for doing it should be in the main() function, did you run it? You can't just run the UCI loop directly, it wouldn't work.
How did you host the engine? Did you host it in the same address space as the server? Note that the engine assumes it's in a different address space because this is how a desktop GUI would work.
Print out everything you send to Stockfish and everything you receive from the engine. Don't assume your commands would work, print everything to a text file. Run the commands in a command line. Stockfish could give you nonsense if one of your commands is not right. You'll have to verify it by trying yourself, don't assume anything.
If you still can't figure out what's happening. Put a breakpoint in the UCI loop and follow it. There has to be something, a condition that makes your search terminate immediately. Don't be afraid, you should be able to debug it yourself if you follow the code step-by-step.
Have you done ucinewgame?


Most likely it's (2), a common mistake in chess programming. If you don't run the setup code correctly, the engine wouldn't be able to run the nega-max algorithm. No nega-max => nothing to search => simply return you the first pawn move.