Contents

Troubleshooting

Find the message or the symptom, then follow the steps.

An agent gets no warnings

  1. Run gitta status in the repository. If the agent is missing, its folder is not a worktree of this repository. Check with git worktree list.
  2. For Claude Code, look in ~/.claude/settings.json for the two gitta hook entries. Add them again with gitta install claude.
  3. For Cursor and Codex, the agent must call gitta_status. Tell it to in your AGENTS.md.
  4. 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:

 Terminal
$ git config --show-scope --get-all core.hooksPath

If 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.

 Terminal
$ git worktree remove .claude/worktrees/detect-language
$ git branch -D worktree-detect-language

A 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.

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.

  1. Run gitta encoding. It shows the code page of each kind of file and the folders that have none.
  2. Set the right code page for the folder in .gitattributes. See Set the code page for each folder.
  3. 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.

  1. 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.
  2. Let the agent fix its code in its own worktree. It often already has, because gitta told it about the clash while it worked.
  3. 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

  1. Run gitta team whoami. If it fails, the machine cannot reach a server or the token is wrong.
  2. Check the server with curl https://gitta-1.example.com/healthz.
  3. With a private certificate authority, set GITTA_SERVER_CA.
  4. Both machines must use the same repository. gitta identifies it by the address of the remote origin, so [email protected]:miguelgrinberg/microblog.git and https://github.com/miguelgrinberg/microblog match. A repository without origin is identified by its folder name.
  5. 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 messageFix
not in an allowed domainAdd the domain to GITTA_OIDC_DOMAINS, or sign in with a company account.
issued for another applicationGITTA_OIDC_CLIENT_ID does not match the application the person signed in to.
the email is not verifiedThe 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 allowedEntra ID. Add the tenant ID to GITTA_OIDC_TENANTS, or sign in with an account of your own tenant.
no allowed tenants are setEntra 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 expiredCheck the server's clock, then sign in again.