# Common quirks and troubleshooting

Agent Mission Control developer docs > Claude skill, self-hosted

> Skill patterns to catch before you generate, and the errors a self-hosted skill agent most often hits.

**Before you start:** A generated agent, or a skill you are about to convert.

## Check the skill before you convert it

| Symptom in the skill | What to do |
| --- | --- |
| Scripts hardcode `/sessions/<session-id>/...` paths | Create the exact path in the Dockerfile and flag the brittleness. One `mkdir` usually covers every script. |
| `SKILL.md` names a CLI tool, or scripts call `subprocess`, `os.system`, or `os.popen` | Install the binary in the Dockerfile, at the exact path the skill looks for it. |
| A bootstrap or auth flow references `tokens.json` or `~/.config/<name>/` | Do not bake credentials or wire OAuth into the agent. Do the first OAuth login on a laptop with the same skill in Claude Code, upload the tokens to a file share, mount it, and point the skill's env var at the mount. |
| Imports such as `feedparser`, `youtube-transcript-api`, `arxiv`, or `praw` | Add them to the dependencies and confirm the container's egress can reach the public internet. Check the skill tolerates one source failing. |
| Multi-MB outputs | File share for files under 100 MB; blob storage (blobfuse or an upload sidecar) for larger or many files. Note size estimates in the README. |
| The skill calls other skills | Bake every skill it needs into `/app/.claude/skills/`, say so in the prompt, and use the multi-purpose pattern. |
| The skill keeps state (`state.json`, `history.db`) | Mount a file share on the state directory. Per-conversation state needs a context id from the caller; treat that as out of scope for a first version. |
| The skill needs a newer Python | The image uses `python:3.12-slim`. Bump it if needed; never go below 3.10, which the SDK requires. |
| Scripts call `input()` or `getpass()`, or open an editor | Not viable unattended. Refactor the skill to take everything through arguments or env first. |
| The skill imports a package that is not on PyPI | Stop. That is a blocker. |

## Errors and what they mean

| You see | Cause and fix |
| --- | --- |
| `/health` returns `not_configured` | Read the missing-vars list in the response body's `detail`. |
| AMC registration says **Unreachable** but the container is running | `/health` returned 503 because the health probe is not ready, or the URL redirects. See [Deploy and register in AMC](https://www.agentmissioncontrol.ai/developers/self-hosted-deploy-and-register/). |
| The agent runs but never invokes the skill | Check `/app/.claude/skills/<skill-name>/SKILL.md` exists in the container, `SKILL_NAME` matches the frontmatter `name:`, `allowed_tools` includes `"Skill"`, and `setting_sources=["project"]` is set. |
| `--dangerously-skip-permissions cannot be used with root/sudo privileges` | Something switched to `bypassPermissions` while running as root. Restore `permission_mode="dontAsk"` and the non-root user. |
| `Permission denied` when the skill writes | The directory is missing from `{{NONROOT_EXTRA_DIRS}}`, so user `claude` does not own it. |
| `JSON message exceeded maximum buffer size` | A message passed the SDK's 1 MiB framing limit. Set `CLAUDE_AGENT_MAX_BUFFER_BYTES`. |
| A `Run used N turns (max_turns=50)` warning that says `approaching cap` | Raise `CLAUDE_AGENT_MAX_TURNS`. |
| `Error: assistant message error: authentication_failed` (or `billing_error`, `rate_limit`) | Credentials, billing, or quota. Run `tests/test_foundry_direct.py` to isolate it. |
| `Error: agent completed but produced no text response` | Look for an earlier `AssistantMessage` error or a `ResultMessage flagged is_error=True` line in the logs. |
| 401 from Foundry | Run `tests/test_foundry_direct.py`, then `test_anthropic_sdk_foundry.py`, to find which layer fails. |
| Phase 1 fails with `Claude Code returned an error result` | Run `tests/debug_sdk.py` for the full message dump. Check the SDK is at least 0.2.138. |
| Tokens always report 0 | Code reads flat `input_tokens` attributes that do not exist. Read `ResultMessage.model_usage`. |
| AMC prices the run at the default rate | `step_completed` has no `model`. Pass it, with `cached_input_tokens`. |
| A failed run shows zero cost in AMC | `set_step_tokens` and `set_cost` were not called before re-raising. |
| Prompt tokens are much higher than the job needs | `tools=` is unset, so the full Claude Code toolset is defined in every prompt. Set it to the base set. |

> **Note:** A slow failure that looks like a hang is often the CLI retrying. `CLAUDE_CODE_MAX_RETRIES` bounds it at 5 by default.

## Related

- [Test the agent locally](https://www.agentmissioncontrol.ai/developers/self-hosted-testing/)
- [Build the Docker image](https://www.agentmissioncontrol.ai/developers/self-hosted-docker/)
- [Configuration and environment](https://www.agentmissioncontrol.ai/developers/self-hosted-configuration/)

---
Source: https://www.agentmissioncontrol.ai/developers/self-hosted-troubleshooting/ · Last updated 2026-10-21 · Full index: https://www.agentmissioncontrol.ai/llms.txt
