Troubleshooting¶
Host and infrastructure issues that present as Bubo misbehaving but are fixed in the environment, not in Bubo. Each entry is symptom → cause → fix. For normal operation — deploy, schedule, grade, report — see Operate.
"No findings" on a change that isn't clean¶
Symptom
- A review (usually an MCP-triggered
review_change) returns no findings on a change that is not genuinely clean. - The transcript or report file shows:
- An anomalous spike in
no_findings. Codex exits 0, so nothing flags it.
Cause
[agents].codex_sandbox (read-only or workspace-write) isolates the run with
bubblewrap, which needs an unprivileged user namespace. An npm/global Codex
ships its own bwrap with no AppArmor profile; on Ubuntu with
kernel.apparmor_restrict_unprivileged_userns = 1 the kernel blocks it, and every
git/shell tool the agent needs fails. The poller usually survives (its diff is
embedded in the prompt); the MCP path fails because it runs Codex nested with no
checkout and must shell out to git. An apt/distro Codex uses the system bwrap,
which has an allowed profile — hence "it works when installed via apt".
Confirm the restriction is on:
Fix — AppArmor distros (Ubuntu, Debian, openSUSE)
Grant the user-namespace capability to Codex's own bundled bwrap. Locate it:
BWRAP=$(find "$(dirname "$(dirname "$(readlink -f "$(command -v codex)")")")" \
-path '*codex-resources/bwrap' 2>/dev/null | head -1)
echo "$BWRAP"
Install a profile and reload AppArmor:
PROFILE=/etc/apparmor.d/codex-bwrap
sudo tee "$PROFILE" >/dev/null <<EOF
abi <abi/4.0>,
include <tunables/global>
$BWRAP flags=(default_allow) {
userns,
include if exists <local/codex-bwrap>
}
EOF
sudo apparmor_parser -r "$PROFILE"
Verify:
"$BWRAP" --unshare-net --ro-bind / / --proc /proc --dev /dev /bin/echo ok # → ok
codex exec --profile bubo --skip-git-repo-check --ephemeral 'run: echo ok' # → ok
- If
apparmor_parser --versionis < 4.0, setabi <abi/4.0>to your parser's abi (e.g.abi <abi/3.0>on Ubuntu 22.04) or drop theabiline. - A Codex upgrade can move the bundled
bwrap; re-run the locate step andapparmor_parser -r.
Fix — non-AppArmor hosts
- RHEL / Fedora / Rocky / Alma (SELinux): the AppArmor sysctl and profile
don't apply. User namespaces are usually allowed; if not, check
sysctl user.max_user_namespaces(must be> 0). - Arch / other: userns usually works out of the box; if
bwrapstill fails, confirmkernel.unprivileged_userns_clone = 1.
Alternatives (no profile)
sudo apt install bubblewrap(Debian/Ubuntu) — Codex prefers abwraponPATH, and the distro package ships an allowed profile. Confirm withcommand -v bwrap→/usr/bin/bwrap.- On a dedicated, credential-stripped host, set
codex_sandbox = "danger-full-access"in[agents]. Notworkspace-write— it is also bubblewrap-based and fails identically. - Avoid disabling
kernel.apparmor_restrict_unprivileged_usernshost-wide unless the host is fully isolated.
Make it visible
Because this hides as "no findings", ship poller stdout to your observability
stack and alert on an anomalous no-findings rate (see
Metrics & telemetry). To check a single run by hand, grep its
report file for bwrap:.