Troubleshooting
Relevant source files
The following files were used as context for generating this wiki page:
Troubleshooting Marginalia involves diagnosing issues across the GitLab poller, the Claude Code CLI execution environment, and the local React-based review studio. Because the system runs headless commands in dedicated git worktrees, errors often stem from environment configuration, tool permissions, or API communication failures.
This page details the diagnostic utilities provided by the project and maps common error signatures to their resolutions.
Diagnostic Tools
Marginalia includes a "Doctor" utility to perform read-only health checks on the environment and specific merge requests (MRs).
System Health Checks
You run npm run doctor to validate your .env configuration, GitLab token scopes, and local repository paths. Each failure in the doctor output includes specific instructions for fixing the detected issue.
Sources: README.md:21-23
Command Dry Runs
If a specific MR fails to review, you use the dry-run flag to execute the full command chain and capture the output to a temporary file:
npm run doctor -- --dry-run <MR_IID>
This is the primary method for debugging commands from plugins or custom agents that do not appear in standard logs.
Sources: README.md:23-24, README.md:257-258
Common Bot Failures
The bot poller manages the lifecycle of a review run. Failures typically occur during the claude -p execution phase within the bot worktree.
Error Reference Table
| Error Message | Cause | Resolution |
|---|---|---|
did not produce a report | The Claude command finished without writing to .marginalia-report.md or printing a <<<REVIEW_FILE>>> block. | Run npm run doctor -- --dry-run <iid> to inspect the raw command output. |
Tool refused | The command attempted to use a CLI tool not permitted by the Marginalia sandbox. | Add the tool name to CLAUDE_EXTRA_ALLOWED_TOOLS in your .env file. |
MR skipped, branch checked out elsewhere | The MR branch is currently checked out in your main working copy or another worktree. | Switch branches in your local checkout; the bot retries on the next poll. |
Command not found | Headless mode cannot resolve the path to a custom plugin or command. | Use the full path or ensure the command is in a trusted directory like ~/.claude. |
Sources: README.md:253-258, README.md:28-36
Execution Flow and Failures
The following diagram illustrates the review process and where common failures interrupt the flow:
The bot environment explicitly strips ANTHROPIC_API_KEY to prevent accidental API-key billing and uses the logged-in CLI session.
Sources: README.md:65-72, README.md:270-280
Studio and API Troubleshooting
The studio serves as a local web interface at http://localhost:4477. Issues here usually relate to build state or API authorization.
API Response Codes
The Studio API (studio/server.mjs) returns specific HTTP status codes to indicate failure modes:
- 403 Forbidden: Occurs when attempting to post a comment or submit a review while
ALLOW_POSTINGis set tofalse. It also triggers if the requestHostorOrigindoes not match the studio's own address (protection against DNS-rebinding). - 409 Conflict: Occurs in two scenarios:
- When attempting to add a comment that has already been posted (
posted.jsonmatch). - When attempting to push fixes via
ALLOW_PUSHbut the remote branch has moved since the triage was performed.
- When attempting to add a comment that has already been posted (
- 502 Bad Gateway: Indicates that a call to the GitLab API failed or timed out. The response body contains the first 300 characters of the GitLab error message.
Sources: studio/public/openapi.yaml:185-230, studio/src/lib/api.ts:250-265
Live Update Failures
The studio uses Server-Sent Events (SSE) via the /events endpoint to refresh data. The server sends data: changed whenever the reviews directory or status.json is updated. If the studio does not refresh:
- Verify the bot is running (
npm run autostart -- --status). - Check for
status.jsonupdates in the root directory. - Ensure the browser has not blocked the SSE connection.
Sources: studio/public/openapi.yaml:231-236, studio/src/lib/api.ts:159-170
Sandboxing and Permissions
Marginalia runs Claude commands within a sandbox defined in lib/claude-sandbox.mjs to protect sensitive local files.
Sandbox Constraints
- Bash Limitations: Writes are restricted to the bot worktree, the repository's
.gitfolder, and thereviews/directory. - Network: Only communication with the configured GitLab host is permitted.
- Protected Files: The sandbox denies access to
~/.ssh,~/.aws, and the bot's own.envfile. - Tool Denials: Read, Edit, and Write tools are kept away from shell configuration files (e.g.,
.zshrc) and the trusted.claude/directory in your main checkout.
If a command fails due to these restrictions and you trust the environment, you can disable the sandbox by setting CLAUDE_SANDBOX=false in .env.
Sources: README.md:264-278
Triage Fixes Issues
The triage system manages local commits for peer comments on your own MRs.
Branch State Mismatches
The studio tracks the state of local fixes against the remote origin.
- Outdated: The branch moved on GitLab after the triage ran. You must re-run the triage command to sync the logic.
- Pushed: The fixes are already present on the remote branch.
- Ready: The fixes exist locally on a
marginalia/<branch-slug>branch and can be fast-forwarded to origin.
Sources: studio/public/openapi.yaml:166-180, studio/src/lib/api.ts:285-295
Sources: studio/public/openapi.yaml:166-175