langgenius/dify · error · AppUnavailableError

app_unavailable

app_unavailable

Error message

App unavailable, please check your app configurations.

What it means

HTTP 400 with error_code app_unavailable, raised by GET /console/explore/installed-apps/<id>/messages when installed_app.app_with_session(session) returns None. The InstalledApp exists but its related App cannot be loaded, so message pagination cannot proceed.

Source

Thrown at api/controllers/console/explore/message.py:82

    ExploreMessageInfiniteScrollPagination,
    ResultResponse,
    SuggestedQuestionsResponse,
)


@console_ns.route(
    "/installed-apps/<uuid:installed_app_id>/messages",
    endpoint="installed_app_messages",
)
class MessageListApi(InstalledAppResource):
    @console_ns.doc(params=query_params_from_model(MessageListQuery))
    @console_ns.response(200, "Success", console_ns.models[ExploreMessageInfiniteScrollPagination.__name__])
    @with_current_user
    def get(self, current_user: Account, installed_app: InstalledApp):
        session = db.session()
        app_model = installed_app.app_with_session(session=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()
        args = MessageListQuery.model_validate(request.args.to_dict())

        try:
            pagination = MessageService.pagination_by_first_id(
                app_model,
                current_user,
                args.conversation_id,
                args.first_id or None,
                args.limit,
                session=session,
            )
            adapter = TypeAdapter(ExploreMessageListItem)
            items = [
                adapter.validate_python(MessageResponseSource(message, session=session), from_attributes=True)

View on GitHub (pinned to ef8544b173)

Solutions

  1. Guard the UI: before opening messages, verify the app via GET /installed-apps/<id> and handle app_unavailable.
  2. Have the owning tenant restore or republish the App.
  3. Clean up installed_apps rows whose App is missing (admin sweep).
  4. Show a 'no longer available' state and offer to remove the installed-app entry.

Example fix

// before: open message list directly
const msgs = await get(`/installed-apps/${id}/messages`);

// after: preflight the app and degrade gracefully
const app = await get(`/installed-apps/${id}`);
if (!app) return showUnavailable();
const msgs = await get(`/installed-apps/${id}/messages`);
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the backing app is reachable before loading messages
const app = await get(`/console/explore/installed-apps/${id}`);
if (!app) return; // backing App unavailable; do not call messages

Type guard

function appIsAvailable(app) {
  return app !== null && app !== undefined;
}

Try / catch

try {
  return await get(`/console/explore/installed-apps/${id}/messages`);
} catch (e) {
  if (e.code === 'app_unavailable') {
    showAppUnavailableState(id);
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: GET messages for an installed app whose underlying App row is gone or unreadable. Triggered by the same conditions as error 743 (owner deleted/unpublished) but hit on the messages sub-resource.

Common situations: App owner deleted the app after another tenant installed it; relational mapping broken (app_id FK stale); the installed-app tile is still on the dashboard but the backing app is dead.

Related errors


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