langgenius/dify · error · NotFound

App not found

Error message

App not found

What it means

Raised as werkzeug NotFound (HTTP 404) from _get_app_ref: no App row matches the given app_id under the current tenant with status='normal'. The helper builds an AppRef for annotation endpoints and refuses to proceed for a missing, deleted, or wrong-tenant app. Note it filters on status='normal', so a disabled/deleted App also yields this.

Source

Thrown at api/controllers/console/app/annotation.py:57

from libs.login import current_account_with_tenant, login_required
from models.model import App
from services.annotation_service import (
    AppAnnotationService,
    EnableAnnotationArgs,
    UpdateAnnotationArgs,
    UpdateAnnotationSettingArgs,
    UpsertAnnotationArgs,
)
from services.app_ref_service import AppRef, AppRefService


def _get_app_ref(session: Session, app_id: str) -> AppRef:
    _, current_tenant_id = current_account_with_tenant()
    app = session.scalar(
        select(App).where(App.id == app_id, App.tenant_id == current_tenant_id, App.status == "normal").limit(1)
    )
    if app is None:
        raise NotFound("App not found")
    return AppRefService.create_app_ref(app)


class AnnotationReplyPayload(BaseModel):
    score_threshold: float = Field(..., description="Score threshold for annotation matching")
    embedding_provider_name: str = Field(..., description="Embedding provider name")
    embedding_model_name: str = Field(..., description="Embedding model name")


class AnnotationSettingUpdatePayload(BaseModel):
    score_threshold: float = Field(..., description="Score threshold")


class AnnotationListQuery(BaseModel):
    page: int = Field(default=1, ge=1, description="Page number")
    limit: int = Field(default=20, ge=1, description="Page size")
    keyword: str = Field(default="", description="Search keyword")

View on GitHub (pinned to ef8544b173)

Solutions

  1. Confirm SELECT id, status, tenant_id FROM apps WHERE id=<app_id> returns a row with status='normal' for the caller's tenant.
  2. If the App was soft-deleted, restore it to status='normal' or stop referencing it.
  3. Ensure the calling account belongs to the tenant that owns the App.
  4. Reload the App list in the console to obtain a current app_id.
Defensive patterns

Strategy: validation

Validate before calling

from sqlalchemy import select
from models.model import App

def app_is_normal(session, app_id: str, tenant_id: str) -> bool:
    return session.scalar(
        select(App.id).where(
            App.id == app_id, App.tenant_id == tenant_id, App.status == 'normal'
        ).limit(1)
    ) is not None

Try / catch

from werkzeug.exceptions import NotFound

try:
    call_annotation_endpoint(app_id=app_id)
except NotFound as exc:
    if 'App not found' in str(exc):
        reload_app_list()
    raise

Prevention

When it happens

Trigger: Calling any annotation endpoint that funnels through _get_app_ref (annotation settings, annotations list/create) with an app_id that does not exist, belongs to another tenant, or has status != 'normal' (e.g. soft-deleted).

Common situations: App was soft-deleted (status set to something other than 'normal'); cross-tenant app_id; stale client reference after the App was removed; app_id typo or copy from another environment.

Related errors


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