Contents
Troubleshooting
Find the message or the symptom, then follow the steps.
An agent gets no warnings
- Run
gitta statusin the repository. If the agent is missing, its folder is not a worktree of this repository. Check withgit worktree list. - For Claude Code, look in
~/.claude/settings.jsonfor the twogitta hookentries. Add them again withgitta install claude. - For Cursor and Codex, the agent must call
gitta_status. Tell it to in yourAGENTS.md. - Warnings come once. An agent that already saw a warning does not see it again.
A worktree runs the main checkout's Git hooks
Claude Code can write an absolute core.hooksPath into a worktree's config.worktree, so Git hooks such as pre-commit run the main checkout's copy (Claude Code issue #88747). gitta's warnings reach the session through Claude Code hooks, and its merge check runs in the checkout where you merge into main, so both work as usual. To see which hooks a worktree runs:
$ git config --show-scope --get-all core.hooksPathIf a worktree line points into another checkout, remove it with git config --worktree --unset core.hooksPath. See Git hooks in Claude Code worktrees.
"git worktree add" fails, or .git/worktrees is read-only
On Linux, CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 makes .git/worktrees/ read-only to the agent's Bash commands. git worktree add then fails, and so do commits inside a worktree (Claude Code issue #101546). gitta keeps its own state in .gitta/ in the main checkout, and gitta sync writes files in the worktree folder, so warnings and sync carry on. For the agent's own commits, start the session without the variable, or make the worktrees from your own terminal with git worktree add before you start the agents.
An old worktree stays after a squash merge
After a squash merge, the worktree's commits are not on main, so cleanup tools can keep the worktree (Claude Code issue #102671). gitta counts every worktree in git worktree list as an agent, so the old one stays in gitta status. Its work is already on main. Remove the worktree, and gitta drops the agent at its next run.
$ git worktree remove .claude/worktrees/detect-language
$ git branch -D worktree-detect-languageA resumed session says "could not verify worktree"
The Claude desktop app checks a worktree with a git fetch before it resumes a session in it. When the fetch times out, the resume stops (Claude Code issue #96091). The worktree and gitta's record of the agent are unchanged. Check that git fetch origin works from that machine, then resume again. The session's warnings continue from where they were.
Two agents changed the same file in different worktrees
Worktrees keep the edits apart, so neither agent sees the other's change. gitta compares them.
- Both agents changed the same function or the same lines. Each one gets an also editing note, and gitta merges the two changes by structure.
- One agent changed a function that the other agent's new code uses, in the same file or another one. The second agent gets a warning with the other agent's new definition. The tests run on the combined code when you merge.
- The two changes cannot be combined. git names the file at merge time, and the second agent resolves it in its own worktree after
gitta sync.
Run gitta status to see all of these at once. See Kinds of warning.
A file shows as changed, but nobody changed it
On mainframe repositories this usually comes from a code page. Git converts the file between EBCDIC and UTF-8 with the working-tree-encoding in .gitattributes. When that setting changes, or a folder gets the wrong code page, every line can differ by a few characters such as [ and ]. gitta reports a change that differs only in those characters as a weakened check, with code page conversion changed characters.
- Run
gitta encoding. It shows the code page of each kind of file and the folders that have none. - Set the right code page for the folder in
.gitattributes. See Set the code page for each folder. - Check out the file again with
git checkout -- <file>. Git converts it with the new setting.
"gitta: skipped <agent>: ..."
gitta could not read one worktree. It leaves that worktree out and keeps working for all the others. The line names the worktree, the reason and the fix. The agent in that worktree is told once that gitta cannot check its work.
The commit the agent started from is gone. This happens after git gc removed a rewritten branch, or in a shallow clone.
gitta: skipped a69: the commit it started from (1c5976ee8281) is no longer in this repository (removed by `git gc`, or the clone is shallow). Fix: `gitta adopt --reset a69` to restart its record from where it meets the main branch now, or `git fetch --unshallow` in a shallow clone
Run gitta adopt --reset a69. In a shallow clone, run git fetch --unshallow instead and the agent comes back as it was.
The worktree's folder is gone.
gitta: skipped a67: its folder /work/wts/a67 is gone (deleted, or on a disk that is not mounted). Fix: `git worktree prune` if it was deleted, or mount the disk again
Run git worktree prune if you deleted it. If it lives on another disk, mount that disk. Locked worktrees and worktrees on a detached HEAD are read as usual.
"gitta: tests fail on main with ..."
gitta stopped a git merge, git pull or git push because the tests fail on the combined code. main does not move. The message names the failing test and its first error line.
- Nothing to clean up. gitta cancels the stopped merge attempt by itself, stops a fast-forward before the branch moves, and a failed push sends nothing. Only when you had other uncommitted changes does it ask you to run
git merge --abort. - Let the agent fix its code in its own worktree. It often already has, because gitta told it about the clash while it worked.
- Merge again.
"... was not merged: .gitta.toml sets weakened_checks to block"
The incoming work removes tests or weakens a security check, and the team policy stops such merges. Ask the agent to restore what it removed, then merge again. If the change is right, the team can change weakened_checks in .gitta.toml with a reviewed commit. See Team policy.
"gitta approve runs only for a person"
The optional override comes from a person, not from an agent session or a script. Run the command yourself, in your own terminal, from the main checkout.
Two pull requests fail the gitta check because of each other
Only the newer one should fail. If the older one fails too, it clashes with an even older pull request. Merge in order of age, or mark the one that should wait as draft or label it gitta-skip.
"network rules need Linux 6.7 or later"
The kernel cannot enforce --no-net or --net-port, so the sandbox refuses to start. Update the kernel, or run the agent in a container without a network.
"land refused: ... collides with work that already landed"
This comes from the optional gitta land. The agent's change and merged work change the same code in ways that cannot be combined. Run gitta sync <agent>. gitta names the file. The agent resolves it in its own worktree.
"land stopped: main could not move forward"
This comes from the optional gitta land. Either someone changed main during the landing, or the checkout of main has uncommitted edits in files that the landing touches. Commit or stash those edits, then land again. gitta never overwrites uncommitted work.
The gate passes alone but fails in gitta
The gate runs in a separate checkout under .gitta/wt/, not in your working folder. Files that are not in Git, for example .env or a local build, are not there. Make the gate install and build what it needs, as in CI, for example npm ci && npm test.
Hooks are slow
A hook scans only its own agent's worktree and reuses the last scan of the others. Every other agent counts from its last scan while its checked out commit and index are unchanged, kept in .gitta/cache/. Each agent's own hook keeps its scan current. A few of the oldest scans are refreshed on each run, so edits made without a hook show up within minutes. Meaning checks against landed work are kept too, and redone only when the agent's files, its base or the protected branch change.
gitta status reads every worktree fresh, with one git status each, and reuses the meaning checks it already made.
Slow hooks usually come from many untracked files. Add build folders to .gitignore.
Team server: no "gitta (team)" warnings
- Run
gitta team whoami. If it fails, the machine cannot reach a server or the token is wrong. - Check the server with
curl https://gitta-1.example.com/healthz. - With a private certificate authority, set
GITTA_SERVER_CA. - Both machines must use the same repository. gitta identifies it by the address of the remote
origin, so[email protected]:miguelgrinberg/microblog.gitandhttps://github.com/miguelgrinberg/microblogmatch. A repository withoutoriginis identified by its folder name. - In evaluation, only 5 people get warnings between machines. See Licence.
"gitta server: no admin tokens configured"
The server does not run without a token. Set GITTA_TOKENS or --token-file.
"licence not accepted"
The file was changed or damaged. Use the file exactly as you received it. Contact support for a new copy.
"sign-in refused"
| Reason in the message | Fix |
|---|---|
| not in an allowed domain | Add the domain to GITTA_OIDC_DOMAINS, or sign in with a company account. |
| issued for another application | GITTA_OIDC_CLIENT_ID does not match the application the person signed in to. |
| the email is not verified | The provider sent no email_verified, or sent false. Verify the email at the provider, or make it send the claim. |
| the email is missing or its domain is not verified (xms_edov) | Entra ID. Add the optional claims email and xms_edov to the ID token, and verify the domain in the tenant. |
| a tenant that is not allowed | Entra ID. Add the tenant ID to GITTA_OIDC_TENANTS, or sign in with an account of your own tenant. |
| no allowed tenants are set | Entra ID. Set GITTA_OIDC_TENANTS on every server. |
| not in an allowed Workspace domain (hd) | Google. Sign in with a Workspace account of an allowed domain, not a personal account. |
| issued by another provider, not ... | GITTA_OIDC_ISSUER is wrong. Use the issuer from the provider's discovery document. |
| sign-in expired | Check the server's clock, then sign in again. |