paperclipai/paperclip · error · Error
Could not read execution-target Git context
Error message
Could not read execution-target Git context
What it means
prepareGitHubExecutionEnvironment probes the execution-target's Git context by running a shell script that emits a payload delimited by NUL markers (PAPERCLIP_GIT_CONTEXT_V1 ... PAPERCLIP_GIT_CONTEXT_END). This error is thrown when the probe exits non-zero or the delimited payload is absent from stdout, meaning the target's Git state (roots, remotes, etc.) could not be discovered.
Source
Thrown at packages/adapter-utils/src/execution-target.ts:1655
printf 'PAPERCLIP_RUNNER_NETWORK_ROOT\0%s\0' "$parent/$(basename "$file")"
fi
done
cwd=$(pwd -P)
top=$(git rev-parse --show-toplevel 2>/dev/null) || top=
if [ -n "$top" ] && [ "$(cd "$top" && pwd -P)" = "$cwd" ]; then
for kind in --git-common-dir --git-dir; do
root=$(git rev-parse --path-format=absolute "$kind" 2>/dev/null) || continue
root=$(cd "$root" && pwd -P) || continue
printf 'PAPERCLIP_GIT_METADATA_ROOT\0%s\0' "$root"
done
fi
printf '\0PAPERCLIP_GIT_CONTEXT_END\0'
`;
const result = await adapterExecutionTargetCommandRunner(remote).execute({
command: "sh", args: ["-c", probe, "paperclip-git-context", input.hostCredentials ? "host" : "managed"],
cwd: input.cwd, timeoutMs: 15_000,
});
if (result.exitCode !== 0) throw new Error("Could not read execution-target Git context");
const payload = result.stdout.split("\0PAPERCLIP_GIT_CONTEXT_V1\0")[1]?.split("\0PAPERCLIP_GIT_CONTEXT_END\0")[0];
if (payload === undefined) throw new Error("Could not read execution-target Git context");
discovered = {};
const records = payload.split("\0");
const roots: string[] = [];
const networkRoots: string[] = [];
for (let index = 0; index + 1 < records.length; index += 2) {
const key = records[index]!;
const value = records[index + 1]!;
if (key === "PAPERCLIP_GIT_METADATA_ROOT") roots.push(value);
else if (key === "PAPERCLIP_RUNNER_NETWORK_ROOT") networkRoots.push(value);
else discovered[key] = value;
}
discovered.PAPERCLIP_GIT_METADATA_ROOTS = JSON.stringify([...new Set(roots)]);
discovered.PAPERCLIP_RUNNER_NETWORK_ROOTS = JSON.stringify([...new Set(networkRoots)]);
} else {
const result = await promisify(execFile)(process.execPath, args, { cwd: input.cwd, timeout: 15_000, maxBuffer: 1024 * 1024 });
try { discovered = JSON.parse(result.stdout.split("\0")[1] ?? ""); }View on GitHub (pinned to 01ad858492)
Solutions
- Confirm the target cwd is a valid Git repository on the remote (`git -C <cwd> status`)
- Ensure git is installed and on PATH on the remote target
- Run the probe command manually over SSH to inspect raw output and stray banners
- Fix or bypass shell init files that emit output before the script runs
Example fix
// verify before invoking ssh user@remote 'cd <cwd> && git rev-parse --is-inside-work-tree && git --version' // then retry the operation
Defensive patterns
Strategy: validation
Validate before calling
const st = await runner.execute({ command: 'sh', args: ['-c', `cd ${cwd} && git rev-parse --is-inside-work-tree`], timeoutMs: 10000 });
if (st.exitCode !== 0) throw new Error('target cwd is not a git work tree'); Try / catch
try {
await prepareGitHubExecutionEnvironment(input);
} catch (e) {
if (String(e.message).includes('Could not read execution-target Git context')) {
console.error('verify remote cwd is a git repo and git is installed');
} else throw e;
} Prevention
- Confirm the remote cwd is a valid Git work tree before launching
- Install git on all remote execution targets
- Suppress stdout noise from remote shell profiles that can corrupt framed payloads
- Test the probe script manually over SSH when onboarding a new target
When it happens
Trigger: Remote sh -c probe returns non-zero (git not installed, cwd missing/not a repo, permission issues); shell output lacks the NUL delimiters because a login banner or a different shell swallowed the printf output; probe times out upstream.
Common situations: Running against a directory that is not a Git work tree; remote host without git on PATH; shell profiles printing output that corrupts the framed payload; the managed/host credential mode arg altering script behavior unexpectedly.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- Could not resolve remote PATH for managed GitHub launchers
- SSH fixture prerequisites are incomplete: ${status.ssh.reaso
- SSH env-lab fixture state exists, but the process is not run
- [paperclip] Workspace restore preserved local working tree c
- [opencode-local] Remote model availability probe for "${mode
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/64b47f9a698c3e38.
Report an issue: GitHub.