Skip to content

/snap/bin/node silently exits with code 7 when used as shebang interpreter in subprocess context #97

@monperrus

Description

@monperrus

Summary

When a Node.js script uses #!/usr/bin/env node and is spawned as a subprocess, the snap wrapper at /snap/bin/node silently exits with code 7 (no stderr output). The identical script works correctly when invoked with /snap/node/current/bin/node directly.

Environment

OS Ubuntu 25.10 (kernel 6.17.0-23-generic, amd64)
snap node 22.22.3 (22/stable, rev 11560)
snapd 2.75.2
`/snap/bin/node` symlink → `/usr/bin/snap`
`/snap/node/current` symlink → `11560`

Steps to reproduce

# Works fine — direct binary
timeout 5 /snap/node/current/bin/node /path/to/pyright/langserver.index.js --stdio </dev/zero
# exit 124 (timeout), pyright LSP output received on stdout

# Fails — snap wrapper
timeout 5 /snap/bin/node /path/to/pyright/langserver.index.js --stdio </dev/zero
# exit 7, no output at all

The failure also manifests whenever a script with #!/usr/bin/env node is spawned as a subprocess and /snap/bin is the first node entry in PATH — e.g., the pyright-langserver language server script launched by editor tooling.

What /snap/bin/node does

strace -e trace=execve /snap/bin/node --version shows the wrapper performing a double execve:

execve("/snap/bin/node", [...], /* 110 vars */) = 0
execve("/snap/snapd/current/usr/bin/snap", ["/snap/bin/node", "--version"], /* 110 vars */) = 0

This chain works when called interactively. It fails silently (exit 7) when the wrapper is the shebang interpreter of a subprocess whose parent process is not a full login shell.

Impact

Any tool that relies on #!/usr/bin/env node and is spawned as a subprocess (language servers, build tools, test runners) will silently fail on systems where snap node's /snap/bin/node is the first node in PATH.

Observed with: pyright-langserver (pyright 1.1.409) launched by Claude Code's pyright-lsp plugin.

Workaround

Create a thin wrapper earlier in PATH that delegates to the direct binary:

# ~/.local/bin/node
#!/bin/bash
exec /snap/node/current/bin/node "$@"

Expected behaviour

/snap/bin/node should behave identically to /snap/node/current/bin/node in all execution contexts, including as a shebang interpreter invoked by a subprocess.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions