Troubleshooting landlock-run ENOENT in dsh Web Profile: The Problem Wasn’t Landlock After All
At first glance, the error looked straightforward.
While using the dsh Web profile, an error similar to the following appeared:
spawn .../landlock-run ENOENT
The obvious suspects were:
-
The landlock-runbinary is missing -
The systemd user session is broken -
Sandbox configuration is incorrect -
The Web profile behaves differently from the Headless profile
The investigation started from those assumptions.
After validating each layer one by one, the final result was unexpected. The current environment had a healthy Landlock setup, a functioning systemd user session, working sandbox components, and a correctly configured Web profile. The remaining task was no longer fixing Landlock. It was identifying which historical session had actually produced the ENOENT error.
Verify That the systemd User Environment Is Working
dsh launches isolated subprocesses through systemd user scopes.
The first step was confirming that the user-level systemd instance was healthy.
systemctl --user is-system-running
Output:
running
Next, verify the runtime directory and DBus session address.
echo "XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR"
echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS"
Result:
XDG_RUNTIME_DIR=/run/user/0
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
Both variables were already present and correctly populated.
To validate systemd user scopes directly, run:
systemd-run --user --scope --quiet --collect --expand-environment=no \
--unit=dsh-test \
-- /usr/bin/node -e 'console.log("SYSTEMD_RUN_OK")'
echo "exit=$?"
Output:
SYSTEMD_RUN_OK
exit=0
If this step fails, many later diagnostics become irrelevant because dsh relies on systemd user scopes for subprocess management.
At this stage, the systemd user environment was confirmed to be functioning correctly.
Test Subprocess Execution with the Headless Profile
The next step was isolating the problem from the Web profile entirely.
A simple Bash command was executed through the Headless profile.
dsh --profile headless \
'printf "USER=%s\n" "$(whoami)";
printf "SHELL=%s\n" "$SHELL";
command -v bash;
echo HELLO'
echo "exit=$?"
Output:
USER=root
SHELL=/bin/bash
/usr/bin/bash
HELLO
exit=0
This verified several important things:
| Validation | Result |
|---|---|
| Bash binary exists | Success |
| User identity is valid | root |
| Shell environment is available | /bin/bash |
| Subprocess execution works | Success |
If landlock-run were actually missing, this test would usually fail immediately.
The Web Profile Behaves Differently
The same approach was then attempted against the Web profile.
dsh --profile web \
'printf "USER=%s\n" "$(whoami)";
printf "SHELL=%s\n" "$SHELL";
command -v bash;
echo WEB_TEST_OK'
Result:
error: too many arguments.
Expected 0 arguments but got 1
Another test produced the same outcome:
dsh --profile web \
'id; /usr/bin/env bash -c "echo CHILD_BASH_OK; command -v bash; id"'
Output:
error: too many arguments.
Expected 0 arguments but got 1
At first this looked suspicious.
However, checking the help output clarified the behavior.
dsh --profile web --help
Output:
Usage: dsh --profile web [options]
Serve the DeepSeek Harness browser UI.
The Web profile is not designed as a command execution interface. It launches the browser-based UI service and does not accept shell commands as positional arguments.
That means these errors were unrelated to Landlock or sandboxing. They were simply command-line usage errors.
Export and Inspect the Full Web Profile Configuration
To determine whether the Web profile used a different sandbox implementation, the complete configuration was exported.
dsh --profile web --dump-config > /tmp/dsh-web-config.txt
Several key components appeared in the output:
- id: subprocess
name: '@deepseek-ai/dsh-subprocess-local'
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
- id: sandbox-policy
name: '@deepseek-ai/dsh-sandbox-policy'
- id: bash-sandbox
name: '@deepseek-ai/dsh-bash-sandbox'
The configuration also showed:
mode: workspace-write
And the available permission presets:
read-only
workspace-write
danger-full-access
From a sandbox perspective, the Web profile was using the same core components as the Headless profile:
dsh-subprocess-local
dsh-sandbox-local
dsh-bash-sandbox
No evidence suggested that the Web profile had switched to a different runner or isolation backend.
Check for Custom Profile Overrides
Next, inspect the profile files themselves.
sed -n '1,260p' /root/.dsh/profiles/web/cordis.yml
Result:
[]
Then inspect the patch layer:
sed -n '1,260p' /root/.dsh/profiles/web/cordis.patch.yml
Result:
[]
The Web profile had no user-defined overrides.
There was no custom patch replacing the default sandbox implementation.
Confirm the Active Web Service Process
The running dsh process was identified with:
pgrep -af dsh
Output:
800 node /usr/bin/dsh web --no-open --trusted-host kenfan0108.vip
To verify the exact launch command:
tr '\0' ' ' < /proc/800/cmdline
Output:
node /usr/bin/dsh web --no-open --trusted-host kenfan0108.vip
This confirmed that the active Web UI instance was running exactly as expected.
The Most Important Evidence Came from journalctl
The breakthrough came from reviewing systemd logs.
Search recent user journal entries:
journalctl --user --since "2 hours ago" --no-pager \
| grep -Ei \
'dsh|ENOENT|landlock|sandbox|runner|subprocess|bash'
Among the results were several successful subprocess launches.
Example:
Started dsh-subprocess-8634-9c10d71c9244.scope -
/usr/bin/node
/usr/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-subprocess-local/lib/runner.js
--
/usr/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/landlock-run
--
bash -c "echo HELLO"
Another example:
Started dsh-subprocess-8712-bcceb363dfa8.scope -
...
landlock-run
...
bash -c "printf \"USER=%s\n\" ..."
These log entries established several facts.
Fact 1: landlock-run Exists
The binary path appeared directly in systemd’s execution logs.
A missing executable would never reach this stage.
Fact 2: Node.js Can Spawn landlock-run
The subprocess runner successfully launched the binary.
That rules out the original assumption that Node could not locate the executable.
Fact 3: Landlock Is Applying Confinement Rules
The logs included arguments such as:
--ro /
--rw /tmp
--rw /root
Those confinement rules were successfully passed into the sandbox.
Fact 4: Bash Executes Successfully Inside the Sandbox
The Bash commands completed without failure.
This demonstrates that sandbox creation and command execution were both functioning.
What the Evidence Actually Proves
By the end of the investigation, the following components had been verified:
Landlock kernel support OK
landlock-run binary OK
Node spawn of landlock-run OK
Landlock probe OK
Landlock confinement OK
systemd-run --user OK
Headless profile OK
Web profile sandbox config OK
Web subprocess startup OK
This changes the interpretation of the original error significantly.
The environment is clearly capable of creating the following chain successfully:
systemd scope
→ dsh-subprocess-local
→ landlock-run
→ bash
That makes it unlikely that the current system is suffering from a persistent Landlock failure.
A more plausible explanation is that a specific historical session, subagent execution, or tool invocation encountered a temporary ENOENT condition.
The Next Step Is Historical Log Analysis
At this point, modifying configuration files or reinstalling dsh would be premature.
The more productive direction is finding the original context where the ENOENT occurred.
Search all dsh data:
grep -RniE \
'spawn .*landlock-run|landlock-run.*ENOENT|ENOENT' \
/root/.dsh
Inspect session records:
find /root/.dsh/sessions \
-type f \
\( -name '*.jsonl' -o -name '*.log' -o -name '*.ndjson' -o -name '*.json' \)
And search subagent history:
grep -RniE \
'ENOENT|landlock-run|node-addon-system-linux-x64' \
/root/.dsh/subagent-gc-backup
The infrastructure itself has already been validated.
The remaining challenge is locating the exact session, subagent, or historical execution that originally generated the landlock-run ENOENT message.
Quick Diagnostic Checklist
-
Verify systemctl --user is-system-running -
Check XDG_RUNTIME_DIR -
Check DBUS_SESSION_BUS_ADDRESS -
Test systemd-run --user -
Validate Bash execution through the Headless profile -
Export the Web profile configuration -
Inspect cordis.patch.yml -
Verify the active Web service process -
Review subprocess startup logs in journalctl -
Search session and subagent history for ENOENT records
FAQ
Why can’t the Web profile execute shell commands?
The Web profile is designed to launch the browser-based DeepSeek Harness UI. It does not accept shell commands as positional arguments.
Is the too many arguments error related to sandboxing?
No. The error occurs during command-line argument parsing before any sandbox component is involved.
Does landlock-run exist on the system?
Yes. Multiple systemd logs show the executable being launched successfully.
Can Node.js successfully spawn landlock-run?
Yes. The subprocess runner starts it repeatedly without failure.
Is the Headless profile functioning correctly?
Yes. Bash commands execute successfully and return expected output.
Does the Web profile use a different sandbox implementation?
Based on the exported configuration, it uses the same core sandbox components as the Headless profile.
Should dsh be reinstalled?
Current evidence does not support a reinstall.
What is the most useful next troubleshooting step?
Search historical session logs, subagent backups, and dsh records to identify the original context that produced the ENOENT error.

