langgenius/dify · error · NotFound

App entity not found

Error message

App entity not found

What it means

HTTP 404 raised in POST /console/explore/installed-apps after a RecommendedApp row was found, but db.session.get(App, app_id) returned None. This indicates a data-integrity break: the recommended_apps row references an App primary key that no longer exists.

Source

Thrown at api/controllers/console/explore/installed_app.py:210

    @login_required
    @account_initialization_required
    @cloud_edition_billing_resource_check("apps")
    @console_ns.expect(console_ns.models[InstalledAppCreatePayload.__name__])
    @console_ns.response(200, "Success", console_ns.models[SimpleMessageResponse.__name__])
    @with_current_tenant_id
    @model_validate(InstalledAppCreatePayload)
    def post(self, req_data: InstalledAppCreatePayload, current_tenant_id: str):
        recommended_app = db.session.scalar(
            select(RecommendedApp).where(RecommendedApp.app_id == req_data.app_id).limit(1)
        )
        if recommended_app is None:
            raise NotFound("Recommended app not found")

        app = db.session.get(App, req_data.app_id)

        if app is None:
            raise NotFound("App entity not found")

        if not app.is_public:
            raise Forbidden("You can't install a non-public app")

        installed_app = db.session.scalar(
            select(InstalledApp)
            .where(and_(InstalledApp.app_id == req_data.app_id, InstalledApp.tenant_id == current_tenant_id))
            .limit(1)
        )

        if installed_app is None:
            # todo: position
            recommended_app.install_count += 1

            new_installed_app = InstalledApp(
                app_id=req_data.app_id,
                tenant_id=current_tenant_id,
                app_owner_tenant_id=app.tenant_id,

View on GitHub (pinned to ef8544b173)

Solutions

  1. Report to an admin to remove the orphaned RecommendedApp row (or re-create the missing App) — this is a server-side data inconsistency, not a client mistake.
  2. As an admin, run a sweep: SELECT * FROM recommended_apps ra LEFT JOIN apps a ON ra.app_id = a.id WHERE a.id IS NULL; and delete the orphans.
  3. On the client, fall back to the general Explore listing and skip the broken entry.
  4. Add a cascade or periodic cleanup job so deleting an App also removes its RecommendedApp row.

Example fix

-- before: orphan recommended_apps row points at deleted app
SELECT ra.app_id FROM recommended_apps ra
LEFT JOIN apps a ON a.id = ra.app_id
WHERE a.id IS NULL;

-- after: remove orphans so the listing stays consistent
DELETE ra FROM recommended_apps ra
LEFT JOIN apps a ON a.id = ra.app_id
WHERE a.id IS NULL;
Defensive patterns

Strategy: try-catch

Validate before calling

// Client cannot validate server-side data integrity; preflight only confirms recommend status
async function appExists(appId) {
  const r = await fetch(`/console/explore/apps`);
  const list = await r.json();
  return (list.data || []).some(a => a.app_id === appId);
}

Try / catch

try {
  await post('/console/explore/installed-apps', { app_id });
} catch (e) {
  if (e.status === 404 && /App entity not found/.test(e.message)) {
    reportOrphanToAdmin(app_id); // data integrity issue, server-side fix required
  } else throw e;
}

Prevention

When it happens

Trigger: POST /console/explore/installed-apps with an app_id that exists in recommended_apps but whose corresponding row in the apps table has been deleted (hard delete) or never committed. The RecommendedApp foreign-key reference is dangling.

Common situations: An admin deleted the App record while the RecommendedApp entry was left in place; a partial/rolled-back migration; manual DB surgery that removed apps without cleaning recommended_apps; multi-tenant workspace teardown that missed the explore table.

Related errors


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