Skip to content

[Bug] macOS packaged node-pty doubles app.asar.unpacked path, terminal posix_spawn ENOENT #615

Closed

Description

@lyc10031

Environment

  • DSH Desktop 0.10.0 (macOS arm64, packaged app)
  • Bundled Harness 0.1.7-rc.2
  • Bundled node-pty@1.2.0-beta.15
  • This happened before installing dsh-better-sidebar or dsh-remote-ssh, and also reproduces with those plugins bypassed.

Symptom

Opening the built-in terminal reports:

Terminal error: posix_spawn failed: No such file or directory

Root cause / isolated reproduction

The packaged node-pty/lib/unixTerminal.js computes helperPath from native.dir, then applies:

helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');

In this build, node-pty is already under Resources/app.asar.unpacked/node_modules/. This transforms a valid path containing app.asar.unpacked into app.asar.unpacked.unpacked.

With the same native module, /bin/bash, working directory, and environment, passing the computed path to pty.fork gives posix_spawn failed: No such file or directory; passing the actual existing prebuilds/darwin-arm64/spawn-helper path succeeds and returns a PID and FD. This isolates the error to the helper path, not the shell, cwd, or Remote SSH plugin.

// Run using macOS Node against the packaged DSH Desktop node-pty:
const path = require('node:path');
const fs = require('node:fs');
const root = '/Applications/DSH Desktop.app/Contents/Resources/app.asar.unpacked/node_modules/node-pty';
const native = require(root + '/lib/utils.js').loadNativeModule('pty');
const actual = path.resolve(root + '/lib', native.dir + '/spawn-helper');
const computed = actual.replace('app.asar', 'app.asar.unpacked')
  .replace('node_modules.asar', 'node_modules.asar.unpacked');
console.log(fs.existsSync(actual), fs.existsSync(computed)); // true false
const args = ['/bin/bash', [], ['TERM=xterm-256color', 'HOME=' + process.env.HOME,
  'PATH=/usr/bin:/bin'], process.env.HOME, 80, 24, -1, -1, true];
native.module.fork(...args, computed, () => {}); // ENOENT
// In a separate run: native.module.fork(...args, actual, () => {}) succeeds.

Expected

Opening the native terminal starts a shell. Please avoid re-rewriting app.asar.unpacked (e.g. replace only the exact app.asar/ path segment, or avoid this rewrite when the module is already unpacked), and add a packaged macOS PTY smoke test. No app files were modified during diagnosis.

Activity

  1. yaojin3616 commented on Oct 22, 2026

    @yaojin3616
    Contributor

    Follow-up for the current V0.12.2 / Harness 0.2.1-rc.2 baseline: Draft PR #769 restores idempotent default helper-path mapping while preserving the explicit/executable-sibling overrides from the current patch. It is a follow-up to #646, not a claim that the earlier fix was never implemented.

    New full-module regressions: 30 failed before / all 43 passed after; clean install/postinstall, typecheck and build passed. Real native PTY and installed-app acceptance are still pending: all four archive/unpacked x default/external PTY cases are blocked by the current sandbox (posix_openpt Operation not permitted), and the one-shot wider permission request expired without approval. Full suite is not green (2232 passed / 20 failed). Details and acceptance hold are in #769. This release-branch PR does not automatically close the issue.

  2. added a commit that references this issue on Oct 26, 2026
  3. yaojin3616 commented on Oct 28, 2026

    @yaojin3616
    Contributor

    已核对 DSH Desktop v0.13.0 的发布代码,此问题对应的修复/版本更新已随正式版交付。

    macOS node-pty 的 helper 路径映射已改为幂等处理,避免把 app.asar.unpacked 再次改成 app.asar.unpacked.unpacked,并保留显式 helper override。

    发布代码:相关实现。 回归覆盖;本次复核的 7 个相关测试文件共 127 项通过、4 项原生平台用例跳过,不将跳过项视为验收通过。

    请在安装后的 macOS 应用里打开终端或原来的 Remote SSH 入口复测。此次本地路径/布局回归通过,不代表在报告机器上的原生 PTY 已重新验收。

    按已发布的修复关闭此 issue。请升级至 v0.13.0 后复测;如果同一问题仍出现,欢迎在此回复或重开,并提供 Desktop/Harness/插件版本、操作系统及脱敏日志(不要上传 token、账号凭据或完整会话)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions