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

# Troubleshooting

> Diagnose common Idun runtime errors: agent_not_ready, boot engine layer skipped, graph load failures, reload-pipeline rollbacks, and validation errors.

This page covers the runtime errors and log messages you are most likely to hit, what each one means, and how to recover. The error strings below come directly from the engine and standalone source.

<AccordionGroup>
  <Accordion title="Server returns HTTP 503 agent_not_ready">
    **Symptom.** A POST to `/agent/run`, `/agent/stream`, or the deprecated `/agent/invoke` returns:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    { "detail": "agent_not_ready" }
    ```

    **Cause.** The standalone server is running, but no agent has been materialised yet. This is the first-run state before the wizard completes.

    **Fix.** Open `http://<host>:<port>/` in a browser. The chat root detects the unconfigured state and redirects to `/onboarding/`, which scaffolds an agent and seeds the DB. After the wizard completes, the next `/agent/*` call returns 200.

    If you expected an agent to be configured, check the admin panel at `/admin/agent/` to confirm the agent row exists.
  </Accordion>

  <Accordion title="Boot log: engine layer skipped, admin-only mode">
    **Symptom.** At startup the log contains:

    ```
    boot engine layer skipped, admin only mode reason=AssemblyError(...)
    boot engine app started unconfigured (no agent yet, wizard will materialize)
    ```

    **Cause.** The standalone read the DB and could not assemble an `EngineConfig` from the stored rows. This usually happens because no agent row exists yet, or because the seeded YAML failed validation. The server still boots so you can reach `/admin/` and `/onboarding/`, but the `/agent/*` routes return `agent_not_ready` until the agent is materialised.

    **Fix.** Either complete the onboarding wizard, or read the `AssemblyError` reason printed in the log. If your `config.yaml` was supposed to seed an agent on first boot, the YAML failed schema validation; fix the validation error and rerun `idun init`.
  </Accordion>

  <Accordion title="Reload pipeline outcomes">
    Every admin-panel save flows through the three-round validation and reload pipeline in `libs/idun_agent_standalone/services/reload.py`. The response carries one of three statuses, each with a different effect on the running engine.

    <CardGroup cols={3}>
      <Card title="RELOADED" icon="circle-check">
        Validated and applied live. DB committed, engine rebuilt.

        UI toast: *Saved and reloaded.*
      </Card>

      <Card title="RESTART_REQUIRED" icon="rotate-right">
        DB committed, engine NOT rebuilt. Triggered by a structural change (`agent.type` or `agent.config.graph_definition`).

        UI toast: *Saved. Restart required to apply.*
      </Card>

      <Card title="RELOAD_FAILED" icon="circle-xmark">
        Engine refused the new config. DB write rolled back, prior config still active.

        UI toast: *Engine reload failed; config not saved.* Error detail attached.
      </Card>
    </CardGroup>
  </Accordion>

  <Accordion title="Engine reload failed (RELOAD_FAILED)">
    **Cause.** One of:

    * The new `graph_definition` path is wrong or the variable does not export a `StateGraph`.
    * A guardrail config references a guard type the engine cannot instantiate (e.g. missing Guardrails Hub validator).
    * An MCP server is unreachable and the engine could not discover its tools.
    * An observability provider rejected the credentials at init time.

    **Fix.** Read the error detail in the toast (or in the standalone log). The previous config is still active; your agent did not break. Fix the underlying issue in the admin form and resave.
  </Accordion>

  <Accordion title="Round 2 validation failures (HTTP 422)">
    A save that fails Round 2 returns:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "detail": {
        "code": "VALIDATION_FAILED",
        "field_errors": [
          { "loc": ["memory", "type"], "msg": "..." }
        ]
      }
    }
    ```

    **Common causes:**

    * **Framework mismatch**: e.g. setting `agent.type=langgraph` but configuring an ADK `SessionService` for memory. Each framework has its own valid memory and checkpointer set.
    * **Missing required field** for the chosen `agent.type`. The admin UI surfaces these inline; if you hit a 422 via API, the `field_errors` array points at the offending field.

    **Fix.** Resolve the field error and resave. The Round 2 check runs against the *assembled* config (DB rows merged into a synthetic `EngineConfig`), so the error may reference a field that lives in a different admin sub-page than the one you edited.
  </Accordion>

  <Accordion title="Graph load errors">
    **Symptom.** At startup or after a `RESTART_REQUIRED` reboot, the engine fails to initialise with an exception like:

    ```
    FileNotFoundError: graph_definition path does not exist
    ModuleNotFoundError: No module named <module>
    ImportError: cannot import name <variable> from <module>
    TypeError: graph_definition must resolve to a StateGraph or CompiledStateGraph
    ```

    **Cause.** `agent.config.graph_definition` is parsed as `<path_or_module>:<variable_name>` and must resolve to a `StateGraph` (or a `CompiledStateGraph`, from which the engine extracts `.builder`).

    The engine tries the file-path interpretation first, then falls back to Python module import. So `my_agent.py:app` works if `my_agent.py` is in the current directory, and `my_pkg.agents.router:graph` works if `my_pkg` is importable.

    **Fix:**

    * Confirm the path or module exists and exports the named variable.
    * Confirm the variable is a `StateGraph` from `langgraph.graph`, not a custom wrapper or a function. If you have a builder function, call it before assigning to the module-level variable.
    * Confirm `langgraph` is installed in the same environment as `idun-agent-engine`.

    For a worked example, see [Connect your existing agent](/guides/connect-your-agent).
  </Accordion>

  <Accordion title="How to verify the graph loaded">
    If the engine boots without error but you are not sure your graph is the one running:

    1. `GET /health` returns the engine version and `agent_name` field. A non-null `agent_name` means an agent was successfully instantiated.
    2. `GET /_engine/info` (engine-only deployments) returns more detail, including the framework type.
    3. In the admin panel, open `/admin/agent/`. The live LangGraph visualisation reflects the currently loaded graph; if it shows your graph's nodes and edges, the graph is loaded.
    4. Open a trace from `/admin/traces/` and inspect the span tree. The root span name corresponds to your graph's entry node.
  </Accordion>

  <Accordion title="ADK adapter: could not load spec for module">
    **Symptom.** Engine startup fails with:

    ```
    ImportError: Could not load spec for module at <path>
    ValueError: Failed to load agent from <path>:<variable>: ...
    ```

    **Cause.** The ADK adapter (`libs/idun_agent_engine/src/idun_agent_engine/agent/adk/adk.py`) resolves `agent.config.agent` with `importlib.util.spec_from_file_location`, so the value must be a path to a `.py` file. Unlike LangGraph's `graph_definition`, it does **not** fall back to dotted module imports. Values like `my_pkg.agent:root_agent` are interpreted as the literal file `my_pkg.agent`, which doesn't exist, so `spec_from_file_location` returns `None` and the loader raises.

    **Fix.** Rewrite the path in file-path form:

    ```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
    agent:
      type: ADK
      config:
        agent: "./agent.py:root_agent"   # not "agent:root_agent"
    ```

    Relative paths resolve against the working directory you launched the server from. Absolute paths also work.
  </Accordion>

  <Accordion title="Edits to config.yaml don't apply after restart">
    **Symptom.** You edit `config.yaml` (change a model, add an MCP server, tweak a guardrail), run `idun init` again, and nothing changes in the running agent.

    **Cause.** `config.yaml` is a **one-shot bootstrap**, not a runtime config file. The seeder (`libs/idun_agent_standalone/src/idun_agent_standalone/infrastructure/scripts/seed.py`) runs each `_seed_<resource>_if_empty` helper, and every helper bails when the corresponding row already exists. After the first successful boot, the DB is the source of truth and `config.yaml` is effectively ignored.

    **Fix.** Edit through the admin panel at `/admin/` instead. Saves there flow through the three-round validation + reload pipeline and apply immediately (subject to the `RESTART_REQUIRED` rules under "Reload pipeline outcomes" above).

    If you really want to re-seed from YAML, clear the relevant DB rows first. For a clean restart, stop the server, delete `idun_standalone.db` (on Postgres, truncate the seeded tables), then run `idun init` again.
  </Accordion>

  <Accordion title="CLI startup warnings">
    Three deprecation warnings appear on every CLI invocation today:

    ```
    LangChain allowed_objects deprecation
    LiteLLM Bedrock missing
    LiteLLM SageMaker missing
    ```

    Noise from upstream packages, no effect on functionality. Will be filtered in a future release.
  </Accordion>
</AccordionGroup>

## What's next

<Card title="Connect your existing agent" icon="plug" horizontal href="/guides/connect-your-agent">
  minimal config for an existing `StateGraph`
</Card>

<Card title="Production hardening" icon="shield-check" horizontal href="/deployment/hardening">
  production env-var checklist
</Card>

<Card title="SSO" icon="lock" horizontal href="/auth/sso">
  require an OIDC JWT on `/agent/*`
</Card>
