paperclipai/paperclip · error · Error

Could not resolve remote PATH for managed GitHub launchers

Error message

Could not resolve remote PATH for managed GitHub launchers

What it means

To run managed GitHub launchers remotely, the code probes the remote host for its PATH by running a shell command whose stdout embeds the PATH between NUL delimiters (framing so login banners cannot be mistaken for the value). This error means the probe timed out, exited non-zero, or no NUL-framed value could be extracted — so a trustworthy remote PATH is unavailable.

Source

Thrown at packages/adapter-utils/src/execution-target.ts:1569

  env: Record<string, string>,
): Promise<string> {
  if (!target) return env.PATH || process.env.PATH || "/usr/bin:/bin";
  const configuredPath = sanitizeRemoteExecutionEnv(env).PATH;
  if (configuredPath !== undefined) return configuredPath;

  // The provider owns login/profile setup. Query its effective PATH before
  // staging BASH_ENV, rather than substituting the controller's toolchain or
  // a minimal PATH that hides legacy NVM/user-local agent installations.
  const result = await adapterExecutionTargetCommandRunner(target).execute({
    command: "sh",
    args: ["-c", "printf '\\000%s\\000' \"$PATH\""],
    cwd: target.remoteCwd,
    timeoutMs: 15_000,
  });
  // Frame the value so login banners cannot become executable search paths.
  const remotePath = result.stdout.match(/\0([^\0]+)\0/)?.[1];
  if (result.timedOut || result.exitCode !== 0 || !remotePath) {
    throw new Error("Could not resolve remote PATH for managed GitHub launchers");
  }
  return remotePath;
}

/** Read only execution-target Git context; never import the controller's credentials into SSH. */
export async function prepareGitHubExecutionEnvironment(input: {
  target: AdapterExecutionTarget | null | undefined;
  cwd: string;
  env: Record<string, string>;
  hostCredentials: boolean;
  networkAccess: boolean;
}): Promise<Record<string, string>> {
  const script = String.raw`
const fs = require('node:fs');
const path = require('node:path');
const cp = require('node:child_process');
const env = {};
env.PAPERCLIP_RUNNER_NETWORK_ROOTS = JSON.stringify(['/etc/resolv.conf','/etc/hosts','/etc/nsswitch.conf','/etc/ssl/certs','/etc/ssl/cert.pem'].flatMap(p => { try { return [fs.realpathSync(p)]; } catch { return []; } }));

View on GitHub (pinned to 01ad858492)

Solutions

  1. SSH to the target manually and confirm `sh -lc 'echo $PATH'` works and is fast
  2. Trim slow shell init files (nvm/conda lazy-load) so the probe finishes within 15s
  3. Verify the remote default shell emits the PATH cleanly and retry
  4. Check network/SSH stability to the remote target

Example fix

// before: probe times out due to slow .bashrc
// after: make init lazy
# ~/.bashrc
[[ -r ~/.nvm/nvm.sh ]] && lazy_load_nvm
Defensive patterns

Strategy: retry

Validate before calling

const probe = await runner.execute({ command: 'sh', args: ['-c', 'echo $PATH'], timeoutMs: 10000 });
if (probe.timedOut || probe.exitCode !== 0) throw new Error('remote PATH probe unhealthy before launch');

Try / catch

try {
  const p = await resolveRemotePath(target);
} catch (e) {
  if (String(e.message).includes('Could not resolve remote PATH')) {
    // retry once after warming the SSH connection
  } else throw e;
}

Prevention

When it happens

Trigger: Remote SSH command timing out (15s), remote shell failing (exit != 0), login banners or shell init output interfering so the /\0([^\0]+)\0/ match fails, or the remote shell printing nothing framed.

Common situations: Remote host with slow shell startup files (nvm, conda) exceeding the timeout; restricted SSH environments where PATH is not exported; middleware printing banners without the expected NUL framing; transient network failures.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/fb17c0a3496bb93e. Report an issue: GitHub.