# Troubleshooting Start with the result of the failing call: errors carry `error.status`, `error.kind` and Gitea's sanitized message, and the audit log has one event per call (see [audit-logging.md](audit-logging.md)). ## The server does not start | Message or exit | Cause and fix | |---|---| | Exit code 2, "GITEA_TOKEN" required (stdio) | stdio needs `GITEA_TOKEN`. Put it in the client's `env` block, or in an env file passed with `--env-file` (or `AEGIS_ENV_FILE`). A `.env` in the working directory counts only when it is a regular file you own with mode 0600. | | Warning "ignoring ./.env: ..." | The working directory's `.env` is a symlink, owned by someone else or accessible to group or others, so its settings are not loaded. Run `chmod 600 .env`, or pass `--env-file PATH`. See "Which env file is read" in [configuration.md](configuration.md). | | Exit code 2, "env file ... does not exist" | The file named by `--env-file` or `AEGIS_ENV_FILE` is missing or not a regular file. | | Exit code 2, refuses a non-loopback bind | `MCP_HOST` is not loopback and there is no `MCP_BEARER_TOKEN` or complete OAuth setup. Set one of them, or bind `127.0.0.1` behind a reverse proxy. | | Exit code 2, lists OAuth settings | `OAUTH_ENABLED=true` needs `GITEA_OAUTH_CLIENT_ID`, `GITEA_OAUTH_CLIENT_SECRET`, `TOKEN_ENCRYPTION_KEY` and `PUBLIC_BASE_URL`. | | Exit code 2, "cannot decrypt .../oauth-store.json" | `TOKEN_ENCRYPTION_KEY` differs from the key the store was written with (or the file is damaged). The server does not wipe it. Restore the original key, or move `DATA_DIR/oauth-store.json` away to start over (signs every OAuth user out). | | Exit code 2, "owned by another user" or "writable by group or others" (OAuth) | `DATA_DIR` must belong to the user the server runs as and not be group or world writable. Fix the owner or `chmod 700`. | | Validation error naming a setting | See the rules in [configuration.md](configuration.md): URLs must be http(s) without credentials, `PUBLIC_BASE_URL` must be https, secrets need 32 characters, `OAUTH_SCOPES` accepts only granular scopes. | | Startup error listing tool names | `DISABLED_TOOLS` contains names that are not registered. Check [tools.md](tools.md). | ## stdio client shows nothing or breaks stdout carries only JSON-RPC. If a wrapper script prints to stdout before the server starts, the client fails to parse the stream. Logs go to stderr; look at the client's MCP server log. `uvx` needs access to the package index that hosts `aegis-gitea-mcp`, see [packaging.md](packaging.md). ## Tool calls fail | `kind` | Meaning | |---|---| | `unauthorized` (401) | Gitea rejected the token: wrong, expired or revoked. In OAuth mode the user signs in again. | | `forbidden` (403) | The token or the user lacks the scope or permission. Admin tools return this for non-admins. Widen the token scopes (see "Token scopes" in the [README](../README.md)) or change the user's rights in Gitea. Sudo needs a site-admin token. | | `not_found` (404) | The object does not exist, or Gitea hides it from this identity. Also returned for endpoints the Gitea version lacks. | | `validation_failed` (422), `bad_request` (400) | Gitea rejected the values. The message says which. | | `invalid_argument` | The arguments do not match the tool schema (missing, wrong type, extra property, bad owner or repository name). The message gives the path, not the value. | | `timeout`, `upstream_unreachable` | Gitea did not answer within `REQUEST_TIMEOUT_SECONDS`, or the connection failed. Check `GITEA_URL` from the server's host (DNS, TLS, firewall). | | `redirect` | Gitea answered with a redirect, which is never followed. Use the final URL (for example https) as `GITEA_URL`. | | `payload_too_large` | The response is above `MAX_BINARY_BYTES`. Raise it or fetch a smaller object. | | `secret_blocked` | `SECRET_DETECTION_MODE=block` withheld a result containing secret-like content. Use `mask` if that is acceptable. | | `audit_unavailable` | The audit log could not be opened, so the call was refused before it reached Gitea. Fix the permissions of `AUDIT_LOG_PATH` (or `DATA_DIR`) and restart. | | `rate_limited` (429) | Gitea or this server's `RATE_LIMIT_PER_MINUTE` limit. | A result with a `truncated` object was cut to `MAX_TOOL_RESPONSE_ITEMS` or `MAX_TOOL_RESPONSE_CHARS`. Use `page` and `limit` on paginated tools to walk through it. A tool the client cannot see is probably filtered by `TOOLSETS`, `READ_ONLY` or `DISABLED_TOOLS`. Calling a filtered or unknown tool is a protocol error. ## HTTP problems - `GET /health` returns 503 `degraded`: the server cannot reach Gitea (the probe is cached for 10 seconds). Fix connectivity from the server's host. - 401 on `/mcp`: no or wrong bearer token, and no valid OAuth token. The response has a `WWW-Authenticate` header that points clients to the OAuth metadata. - Request rejected with an invalid Host (421): the name you used is not allowed. Add it to `ALLOWED_HOSTS` or set `PUBLIC_BASE_URL`. With a non-loopback `MCP_HOST` and neither variable the server prints a warning at startup that says so. - 429: the client exceeded `RATE_LIMIT_PER_MINUTE`. If every client seems to share one limit, the proxy address is not in `FORWARDED_ALLOW_IPS`, so all requests look like they come from the proxy. - The server exits with code 2 and "cannot open the audit log": the audit file or its directory is not writable. Fix the permissions, or point `AUDIT_LOG_PATH` or `DATA_DIR` at a writable location (in Docker, check the volume ownership). The server never runs without an audit log. - Responses arrive in one chunk or time out behind nginx: set `proxy_buffering off;`. ## OAuth sign-in - The client reports that dynamic client registration is unsupported: OAuth is off. Set `OAUTH_ENABLED=true` and the settings that go with it. - Gitea shows a redirect URI error: the OAuth application's redirect URI must be exactly `/oauth/callback`. Re-run `setup --public-base-url ...` or fix it in Gitea. - Signed in, but admin tools return 403: the user is not a site administrator. That is intended. - Users are asked to sign in again after a restart: the `DATA_DIR` volume changed or was not persistent (a changed `TOKEN_ENCRYPTION_KEY` stops startup instead, see above). Keep the key stable and the volume persistent. - The sign-in page says the request is invalid or expired: the consent page lives 10 minutes and a form is single use. Start the sign-in again from the client. Registration or sign-in refused with "too many": one client address may hold 20 pending sign-ins and register 20 clients per hour. - After fixing OAuth settings the client still fails: some clients cache tokens. Disconnect the server in the client and connect again, which starts a fresh flow. Users can also revoke the application under Settings, Applications, Authorized OAuth2 Applications in Gitea.