langgenius/dify · error · AgentNotFoundError

Agent not found.

Error message

Agent not found.

What it means

Raised as AgentNotFoundError when serializing an Agent App detail: neither the direct Agent lookup (by agent_id) nor roster_service.get_app_backing_agent returned an Agent. The App exists (it passed setup/login) but has no ACTIVE Agent backing it, so the roster-shaped detail cannot be built. This is an inconsistency between the App row and the Agent roster.

Source

Thrown at api/controllers/console/agent/roster.py:388

    roster_service = _agent_roster_service(session)
    payload = AgentAppDetailWithSite.model_validate(
        app_model,
        from_attributes=True,
        context={"session": session},
    ).model_dump(mode="json")
    agent = (
        session.scalar(
            select(Agent).where(
                Agent.tenant_id == app_model.tenant_id,
                Agent.id == agent_id,
                Agent.status == AgentStatus.ACTIVE,
            )
        )
        if agent_id
        else roster_service.get_app_backing_agent(tenant_id=app_model.tenant_id, app_id=str(app_model.id))
    )
    if not agent:
        raise AgentNotFoundError()
    payload.pop("bound_agent_id", None)
    payload["app_id"] = agent.app_id
    payload["backing_app_id"] = roster_service.runtime_backing_app_id(agent)
    payload["hidden_app_backed"] = bool(agent.backing_app_id and agent.backing_app_id != agent.app_id)
    payload["id"] = agent.id
    debug_conversation_id = roster_service.get_or_create_build_conversation(
        tenant_id=app_model.tenant_id,
        agent_id=agent.id,
        account_id=current_user.id,
        commit=False,
    )
    message_count = roster_service.count_agent_app_debug_conversation_messages(
        conversation_id=debug_conversation_id,
    )
    payload["debug_conversation_id"] = debug_conversation_id
    payload["debug_conversation_has_messages"] = message_count > 0
    payload["debug_conversation_message_count"] = message_count
    payload["role"] = agent.role or ""

View on GitHub (pinned to ef8544b173)

Solutions

  1. Confirm an ACTIVE Agent exists for the App: SELECT * FROM agents WHERE app_id=<app_id> AND status='active'; re-create/re-publish if missing.
  2. If the Agent was intentionally deactivated, archive the App or rebind it to an active Agent.
  3. Check bound_agent_id on the App row matches an existing Agent in the same tenant.
  4. In fixtures, ensure the backing Agent row is created and ACTIVE before hitting the detail endpoint.
Defensive patterns

Strategy: validation

Validate before calling

from sqlalchemy import select
from models.agent import Agent, AgentStatus

def app_has_active_agent(session, app_model) -> bool:
    return session.scalar(
        select(Agent.id).where(
            Agent.tenant_id == app_model.tenant_id,
            Agent.app_id == app_model.id,
            Agent.status == AgentStatus.ACTIVE,
        ).limit(1)
    ) is not None

Try / catch

from services.errors.agent import AgentNotFoundError

try:
    detail = fetch_agent_app_detail(app_id)
except AgentNotFoundError:
    # backing Agent missing/non-ACTIVE: rebind or restore before retry
    raise

Prevention

When it happens

Trigger: GET /console/agents/<agent_id>/apps/<app_id> (or the app detail serializer) for an App whose bound_agent_id points to a non-ACTIVE or missing Agent, or whose backing-agent lookup returns None. Distinguishable from 200/201 because it fires in the detail serializer, not the publish-visibility path.

Common situations: App whose Agent was soft-deleted or set to a non-ACTIVE status; app created by an older flow that did not provision the backing Agent; cross-tenant reference; race during Agent deactivation while the detail page is open.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/2837b1d100445cf1. Report an issue: GitHub.