coleam00/Archon · error
Refusing detached run control because process ${String(proce
Error message
Refusing detached run control because process ${String(process.pid)} does not own process group ${String(process.pid)} What it means
assertDetachedRunProcessOwner() verifies, before enabling detached-run control, that the current process is actually the leader of its own process group (processGroupExists(pid) on POSIX). Detached-run cancellation works by signaling the owner's process group; if the process does not lead that group, signaling would hit the wrong processes, so the runtime refuses. Windows skips this check.
Source
Thrown at packages/cli/src/utils/detached-run-control.ts:77
if (process.platform !== 'win32') {
const stat = lstatSync(directory);
if (!stat.isDirectory() || stat.isSymbolicLink()) {
throw new Error(`Detached run control path is not a directory: ${directory}`);
}
if (uid !== undefined && stat.uid !== uid) {
throw new Error(`Detached run control directory is owned by another user: ${directory}`);
}
if ((stat.mode & 0o077) !== 0) {
throw new Error(`Detached run control directory must have mode 0700: ${directory}`);
}
}
return directory;
}
/** Prove the marked POSIX owner has the process group that active cancellation will signal. */
export function assertDetachedRunProcessOwner(): void {
if (process.platform !== 'win32' && !processGroupExists(process.pid)) {
throw new Error(
`Refusing detached run control because process ${String(process.pid)} does not own process group ${String(process.pid)}`
);
}
}
/** A bounded, user-scoped endpoint: Unix socket on POSIX, named pipe on Windows. */
export function detachedRunControlPath(runId: string): string {
const token = endpointToken(runId);
if (process.platform === 'win32') return `\\\\.\\pipe\\archon-workflow-${token}`;
return join(controlDirectory(), `${token}.sock`);
}
function detachedRunControlLockPath(runId: string): string {
return join(controlDirectory(), `${endpointToken(runId)}.lock`);
}
function listen(server: Server, path: string): Promise<void> {
return new Promise((resolve, reject) => {View on GitHub (pinned to 0773b97458)
Solutions
- Launch the detached run through the normal Archon CLI entry point, which sets up its own process group.
- If embedding programmatically, ensure the child is started detached with its own process group (e.g. spawn with detached:true on POSIX).
- Check how your wrapper (docker exec, tmux, CI runner) starts the process and confirm it allows a new process group.
Example fix
// before
spawn('archon', ['run', ...]) // shares parent's pgroup
// after
spawn('archon', ['run', ...], { detached: true, stdio: 'ignore' }).unref() Defensive patterns
Strategy: try-catch
Validate before calling
function isGroupLeader(): boolean {
if (process.platform === 'win32') return true;
return process.getpid() === process.getpgid(process.getpid());
}
if (!isGroupLeader()) throw new Error('Refusing detached run: not a process-group leader'); Try / catch
try {
assertDetachedRunProcessOwner();
await runWorkflowWithOwnedSource(...);
} catch (err) {
if (err instanceof Error && err.message.includes('does not own process group')) {
console.error('Launch the CLI detached (own process group), e.g. spawn(..., { detached: true }).');
} else throw err;
} Prevention
- Always launch detached runs via the Archon CLI entry point rather than embedding in-process.
- Use spawn detached:true when wrapping programmatically on POSIX.
- Avoid process managers that force children into the parent's process group for this path.
When it happens
Trigger: Starting a detached run control server (via runWorkflowWithOwnedSource) on POSIX when the process is not a process-group leader — e.g. it was launched in a way that did not call setpgid(0,0).
Common situations: Embedding the Archon CLI inside another process manager, shell job-control setup, or test harness that runs the process in the parent's process group instead of a fresh one; environments where setpgid failed silently at startup.
Related errors
- Detached run control path is not a directory: ${directory}
- Detached run control directory is owned by another user: ${d
- Detached run control directory must have mode 0700: ${direct
- Detached run control endpoint is already owned: ${path}
- Detached run control endpoint is already owned: ${endpointPa
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/081b8a0f64270313.
Report an issue: GitHub.