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
- Confirm SELECT id, status, tenant_id FROM apps WHERE id=<app_id> returns a row with status='normal' for the caller's tenant.
- If the App was soft-deleted, restore it to status='normal' or stop referencing it.
- Ensure the calling account belongs to the tenant that owns the App.
- 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
- Stop referencing apps after they are soft-deleted (status != 'normal').
- Reload the App list to obtain a current app_id before annotation work.
- Confirm the calling account belongs to the App's tenant.
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
- Snippet not found
- app_not_found
- export response missing data field
- reconnect stream body missing
- unknown
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/ae0db93a9bf0029c.
Report an issue: GitHub.