> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getgaal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Common errors

> What specific error messages mean and how to fix them.

If `gaal sync` or `gaal doctor` is reporting an error, find it on this page. Each entry covers what triggered it, what gaal is actually checking, and the fix.

## "config not found"

```text theme={"theme":"nord"}
✗ no configuration found
  searched:
    --config flag (not provided)
    ./gaal.yaml
    ~/.config/gaal/config.yaml
    /etc/gaal/config.yaml
```

gaal couldn't find any of the four config sources. Either:

* **You meant to be in a project directory**, `cd` to it.
* **You haven't initialised yet**, run `gaal init`.
* **You're scripting gaal in a non-standard location**, pass `--config /path/to/file.yaml`.

## "schema validation failed"

```text theme={"theme":"nord"}
✗ ./gaal.yaml: schema validation failed
    skills[2].agents: expected array of strings, got string
```

The YAML parsed but the structure is wrong for the schema. The error message includes a JSON-pointer path (`skills[2].agents`), go to that location and compare against [the schema reference](/schema/overview).

Tip: install the JSON Schema (`gaal schema -f schema.json`) and your editor will catch this before you save.

## "scope-restricted field in workspace"

```text theme={"theme":"nord"}
! ./gaal.yaml: telemetry cannot be set in a workspace config (ignored)
```

The `telemetry` key is restricted to the user (`~/.config/gaal/config.yaml`) and system (`/etc/gaal/config.yaml`) scopes. The workspace value is ignored. Move it to the user scope.

## "source not reachable"

```text theme={"theme":"nord"}
✗ skills[0].source: anthropics/skills (HTTP 404)
```

The `source:` URL doesn't resolve. Either:

* The repo was renamed or deleted, update the URL.
* It's a private repo and your local credentials don't grant access, check your SSH key / `~/.netrc`.
* You're offline, pass `--offline` to `doctor` or wait until you're online.

## "destination is not empty"

```text theme={"theme":"nord"}
destination src/example is not empty (contains: README.md); gaal refuses to clone into a directory with existing content
```

gaal will not clone a managed repository into a directory that already contains files. Move the existing directory, delete it yourself, or point `repositories:` at a different path.

## "remote URL mismatch"

```text theme={"theme":"nord"}
repositories[src/example]: remote URL mismatch: origin is git@github.com:acme/example.git, config wants https://github.com/acme/example.git
```

For an existing Git checkout, gaal uses the checkout's `origin`. It does not silently retarget the working copy. Either update `url:` in `gaal.yaml` to match the checkout, or run `git remote set-url origin <url>` in the working copy.

## "MCP target file not writable"

```text theme={"theme":"nord"}
✗ mcp "filesystem": ~/.claude.json (permission denied)
```

gaal can't write to the MCP target file resolved from the agent registry. Either:

* The file's permissions are wrong, `chmod 644` it.
* The parent directory exists but isn't user-writable, fix the permissions.
* The path crosses a read-only mount.

If the parent directory is **missing**, gaal silently skips the entry rather than creating an agent-owned directory; install the agent first (or pre-create the directory yourself).

## "MCP target file is not valid JSON"

```text theme={"theme":"nord"}
✗ mcp "filesystem": parsing existing config ~/.claude.json
    invalid character '}' looking for beginning of object key string
```

Someone (you, an installer, an editor crash) wrote invalid JSON into the target file. gaal won't try to fix it because it can't safely tell what was intended. Open the file, fix the syntax, run sync again.

## "target field is deprecated"

```text theme={"theme":"nord"}
! mcp: 'target' field is deprecated; use 'agents' and 'global' instead (name=filesystem)
```

The legacy `target:` field on `mcps[]` still works but logs a warning on every sync. Replace it with `agents:` + `global:` so gaal resolves the path from the registry. See [Configure MCP servers → Migrating from `target:`](/configure/mcp-servers#migrating-from-target).

## "custom agent overrides built-in"

```text theme={"theme":"nord"}
! ~/.config/gaal/agents.yaml: 'cursor' is a built-in agent (custom entry ignored)
```

You can extend the built-in registry with new agents but you can't override existing ones. Rename your custom entry (e.g. `my-cursor`) or remove it.

## "agent skills directory not detected"

```text theme={"theme":"nord"}
! agents: github-copilot is not installed; skills[0] (agents: ["*"]) skipped
```

You used `agents: ["*"]` and one of the registry agents wasn't detected. By default gaal only installs into agents it detects. If you want to install regardless, for example, to pre-stage a fresh machine, pass `--force`:

```bash theme={"theme":"nord"}
gaal sync --force
```

## "service mode rejected"

```text theme={"theme":"nord"}
error: --dry-run and --service are incompatible
```

```text theme={"theme":"nord"}
error: --prune and --service are incompatible
```

These are intentional. `--service` is a continuous loop; `--dry-run` would do nothing forever, and `--prune` is a destructive operation that doesn't belong in an unattended loop. Run those one-shot.

## "VCS binary not found"

```text theme={"theme":"nord"}
✗ repositories[src/legacy/old-tool]: type 'svn' requires the svn binary on $PATH
```

Hg, Subversion, and Bazaar use the system binary. Install it (`brew install subversion`, `apt install subversion`, …) or convert the repository to a Git mirror.

## Still stuck?

Open an issue at [github.com/getgaal/gaal](https://github.com/getgaal/gaal/issues) with:

* The exact command you ran.
* The output of `gaal doctor -o json`.
* The version from `gaal version`.

## Related

<CardGroup cols={2}>
  <Card title="gaal doctor" icon="stethoscope" href="/troubleshooting/doctor" />

  <Card title="FAQ" icon="circle-question" href="/troubleshooting/faq" />
</CardGroup>
