paperclipai/paperclip · error · Error

Local filesystem/network confinement requires the Codex CLI

Error message

Local filesystem/network confinement requires the Codex CLI engine; ACP confinement is not supported.

What it means

Thrown by resolveCodexExecutionEngineForRun when the adapter config explicitly requests engine=acp (the Codex Agent Communication Protocol archive-staging lane) while also setting a filesystemScope or networkScope. ACP stages work in an archive and cannot apply spawn-level OS confinement, so the two settings are mutually exclusive and the resolver refuses to pick one silently.

Source

Thrown at packages/adapters/codex-local/src/server/acp.ts:106

    legacyRemoteExecution: input.executionTransport?.remoteExecution,
  });
  if (target?.workspaceRealization?.mode === "in_place") {
    if (selection.explicit && selection.engine === "acp") {
      throw new Error("In-place workspace realization requires the Codex CLI engine; ACP archive staging is not supported.");
    }
    return {
      engine: "cli",
      explicit: selection.explicit,
      ...(!selection.explicit
        ? { fallbackReason: "In-place workspace realization must run without ACP archive staging." }
        : {}),
    };
  }
  const filesystemScope = parseLocalProcessFilesystemScope(input.config.filesystemScope);
  const networkScope = parseLocalProcessNetworkScope(input.config.networkScope);
  if (filesystemScope || networkScope) {
    if (selection.explicit && selection.engine === "acp") {
      throw new Error("Local filesystem/network confinement requires the Codex CLI engine; ACP confinement is not supported.");
    }
    return {
      engine: "cli",
      explicit: selection.explicit,
      ...(!selection.explicit
        ? { fallbackReason: "Local filesystem/network scope requires spawn-level confinement in the CLI lane." }
        : {}),
    };
  }
  if (selection.explicit || selection.engine !== "acp") return selection;

  const fallbackReason = await defaultCodexAcpFallbackReason(input);
  if (!fallbackReason) return selection;
  return { engine: "cli", explicit: false, fallbackReason };
}

export function formatCodexAcpFallbackMessage(reason: string): string {
  return `[paperclip] Codex ACP default unavailable; falling back to Codex CLI. ${reason} Set engine=acp to require ACP or engine=cli to silence this fallback.\n`;

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. If you need OS-level filesystem/network confinement, set config.engine to "cli" (or omit it so the resolver falls back to CLI with a fallbackReason) and keep the scopes.
  2. If you need ACP archive staging, remove the filesystemScope and networkScope fields from the adapter config so the confinement branch is not entered.
  3. If neither confinement nor ACP is strictly required, drop both engine and the scopes so the resolver can auto-pick ACP or fall back to CLI with a logged reason.

Example fix

// before
adapterConfig = { engine: "acp", filesystemScope: { root: "/workspace" } }
// after — confinement wins, CLI lane
adapterConfig = { engine: "cli", filesystemScope: { root: "/workspace" } }
Defensive patterns

Strategy: validation

Validate before calling

function isCodexEngineConfigCoherent(cfg: { engine?: unknown; filesystemScope?: unknown; networkScope?: unknown }): boolean {
  const engine = typeof cfg.engine === "string" ? cfg.engine.trim().toLowerCase() : "";
  const explicit = engine === "acp" || engine === "cli";
  const hasScope = cfg.filesystemScope != null || cfg.networkScope != null;
  // ACP + scope is the rejected combination
  return !(explicit && engine === "acp" && hasScope);
}
// call before starting the run
if (!isCodexEngineConfigCoherent(adapterConfig)) {
  throw new Error("Refusing to start: engine=acp is incompatible with filesystemScope/networkScope.");
}

Type guard

function isExplicitAcpWithScope(cfg: Record<string, unknown>): boolean {
  const e = typeof cfg.engine === "string" ? cfg.engine.trim().toLowerCase() : "";
  return e === "acp" && (cfg.filesystemScope != null || cfg.networkScope != null);
}

Try / catch

try {
  await resolveCodexExecutionEngineForRun(input);
} catch (e) {
  if (e instanceof Error && /ACP confinement is not supported/.test(e.message)) {
    // auto-downgrade to CLI lane, or surface a config error to the operator
    input.config.engine = "cli";
  } else throw e;
}

Prevention

When it happens

Trigger: A run is started with config.engine explicitly set to "acp" (normalizeEngine maps the trimmed/lowercased value) AND parseLocalProcessFilesystemScope(config.filesystemScope) or parseLocalProcessNetworkScope(config.networkScope) returns a truthy scope. The in-place workspace realization branch (line 90) is NOT the one that fires here; this is the local confinement branch at line 104.

Common situations: Operator copies a hardened CLI-agent profile (which sets filesystemScope/networkScope for sandboxing) onto a company that was configured for ACP, or flips engine to acp to test archive staging without removing the confinement scopes they added for the CLI lane.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/be77ca0957a651f0. Report an issue: GitHub.