coleam00/Archon · critical
Detached run control directory is owned by another user: ${d
Error message
Detached run control directory is owned by another user: ${directory} What it means
After creating the detached-run control directory, controlDirectory() verifies on POSIX that the directory's owning uid matches the current process uid. If another user owns the path, the runtime refuses to use it, since control files there (lock, socket) could be manipulated by that owner. This is a hardening check against pre-created or hijacked control directories in shared /tmp.
Source
Thrown at packages/cli/src/utils/detached-run-control.ts:65
function endpointToken(runId: string): string {
return createHash('sha256').update(runId).digest('hex').slice(0, 32);
}
function controlDirectory(): string {
const uid = process.getuid?.();
const directory =
process.platform === 'win32'
? join(tmpdir(), 'archon-run-control')
: `/tmp/archon-${uid === undefined ? 'user' : String(uid)}`;
mkdirSync(directory, { recursive: true, mode: 0o700 });
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. */View on GitHub (pinned to 0773b97458)
Solutions
- Check ownership: ls -ln /tmp/archon-* and compare the uid with id -u.
- Remove the mis-owned directory if no run is active: sudo rm -rf /tmp/archon-<uid>, then re-run as your user.
- Avoid mixing sudo and non-sudo invocations of detached Archon runs; use a consistent user.
Example fix
// before $ ls -ln /tmp | grep archon drwx------ root root archon-1000 // after $ sudo rm -rf /tmp/archon-1000 $ archon run ... # recreated as uid 1000
Defensive patterns
Strategy: try-catch
Validate before calling
import { lstatSync } from 'node:fs';
function ownedByMe(dir: string): boolean {
try { return lstatSync(dir).uid === process.getuid(); }
catch { return true; }
} Try / catch
try {
const dir = controlDirectory();
} catch (err) {
if (err instanceof Error && err.message.includes('owned by another user')) {
console.error('Control dir mis-owned; remove it as its owner and re-run as your user.');
} else throw err;
} Prevention
- Do not mix sudo and non-sudo Archon invocations.
- Remove stale /tmp/archon-<uid> dirs when switching users.
- Avoid shared multi-uid container setups for the same home/tmp.
When it happens
Trigger: stat.uid from lstatSync(directory) differs from process.getuid() while resolving a detached-run control path or lock path on a non-Windows platform.
Common situations: Another local user created /tmp/archon-<your-uid> first (spoofing the fixed per-uid name); running Archon under sudo after a first run created the directory as root; a shared container where the directory was created by a different uid mapping.
Related errors
- Detached run control directory must have mode 0700: ${direct
- Detached run control path is not a directory: ${directory}
- EACCES
- Error loading workflows: ${err.message} Hint: Check permissi
- Cannot access command file at ${path}: ${err.message}
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/2283ea5ddc635087.
Report an issue: GitHub.