langgenius/dify · error · AppUnavailableError

app_unavailable

app_unavailable

Error message

App unavailable, please check your app configurations.

What it means

AppUnavailableError (HTTP 400, code 'app_unavailable') is raised in ConversationListApi.get at /installed-apps/<id>/conversations when installed_app.app_with_session(session) returns None. The InstalledApp row exists but the underlying App record it references is gone — deleted by the owner, purged, or corrupted.

Source

Thrown at api/controllers/console/explore/conversation.py:59

    console_ns,
    ConversationInfiniteScrollPagination,
    ResultResponse,
    SimpleConversation,
)


@console_ns.route(
    "/installed-apps/<uuid:installed_app_id>/conversations",
    endpoint="installed_app_conversations",
)
class ConversationListApi(InstalledAppResource):
    @console_ns.doc(params=query_params_from_model(ConversationListQuery))
    @console_ns.response(200, "Success", console_ns.models[ConversationInfiniteScrollPagination.__name__])
    @with_current_user
    def get(self, current_user: Account, installed_app: InstalledApp):
        app_model = installed_app.app_with_session(session=db.session())
        if app_model is None:
            raise AppUnavailableError()
        app_mode = AppMode.value_of(app_model.mode)
        if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
            raise NotChatAppError()

        raw_args: dict[str, Any] = {
            "last_id": request.args.get("last_id"),
            "limit": request.args.get("limit", default=20, type=int),
            "pinned": request.args.get("pinned"),
        }
        if raw_args["last_id"] is None:
            raw_args["last_id"] = None
        pinned_value = raw_args["pinned"]
        if isinstance(pinned_value, str):
            raw_args["pinned"] = pinned_value == "true"
        args = ConversationListQuery.model_validate(raw_args)

        try:
            with sessionmaker(db.engine).begin() as session:

View on GitHub (pinned to ef8544b173)

Solutions

  1. Uninstall the orphaned installed app via DELETE /console/explore/installed-apps/<installed_app_id>.
  2. Verify with the app owner whether the app still exists; reinstall from Explore if available.
  3. If this affects many users, check for a batch deletion or migration that removed App rows without cleaning up InstalledApp references.
Defensive patterns

Strategy: validation

Validate before calling

async function appExists(installedAppId) {
  const res = await fetch(`/console/explore/installed-apps/${installedAppId}`);
  return res.ok;
}

Try / catch

try {
  const conversations = await listConversations(installedAppId);
} catch (e) {
  if (e.code === 'app_unavailable') {
    // backing App gone — hide the conversation list, offer uninstall
    showAppUnavailableUI(installedAppId);
  }
}

Prevention

When it happens

Trigger: GET /console/explore/installed-apps/<installed_app_id>/conversations where the original App was deleted by its owning tenant after installation, leaving an orphaned InstalledApp.

Common situations: App owner deleted the app from their workspace; tenant purge removed the App row; database inconsistency; the app is being decommissioned and the App was removed first.

Related errors


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