{"record":{"id":"583b88cbbeeb35a6","repo":"langgenius/dify","slug":"app-not-found-583b88","errorCode":"app_not_found","errorMessage":"App not found.","messagePattern":"App not found\\.","errorType":"error_code","errorClass":"AppNotFoundError","httpStatus":404,"severity":"error","filePath":"api/controllers/console/app/wraps.py","lineNumber":83,"sourceCode":"    (rename/icon sync, archive, API enablement), so it additionally requires\n    workspace ``agent.manage`` on top of the route's existing App permission\n    checks when RBAC is enabled. A no-op for non-agent Apps. Must be placed\n    above ``get_app_model`` so the ``app_id`` path parameter is still present.\n    \"\"\"\n\n    @wraps(view)\n    def decorated(*args: P.args, **kwargs: P.kwargs) -> R:\n        raw_app_id = kwargs.get(\"app_id\") or kwargs.get(\"resource_id\")\n        if raw_app_id is not None:\n            app_model = _load_app_model_from_scoped_session(str(raw_app_id))\n            binding = (\n                app_model.agent_app_binding_with_session(session=db.session(), include_archived=True)\n                if app_model is not None\n                else None\n            )\n            if binding is not None:\n                if binding.scope == AgentScope.WORKFLOW_ONLY:\n                    raise AppNotFoundError()\n                if dify_config.RBAC_ENABLED:\n                    current_user, current_tenant_id = current_account_with_tenant()\n                    enforce_rbac_access(\n                        tenant_id=current_tenant_id,\n                        account_id=current_user.id,\n                        resource_type=RBACResourceScope.WORKSPACE,\n                        scene=RBACPermission.AGENT_MANAGE,\n                        resource_required=False,\n                    )\n        return view(*args, **kwargs)\n\n    return decorated\n\n\ndef _get_injected_session(args: tuple[object, ...]) -> Session | None:\n    \"\"\"Return the request session inserted by `with_session`, if this handler has been migrated.\"\"\"\n    if len(args) < 2:\n        return None","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/app/wraps.py#L65-L101","documentation":"Raised by the app_data_view decorator when an app is bound to an Agent App with AgentScope.WORKFLOW_ONLY. Such hidden backing apps power a roster Agent but are not part of the general app management plane, so generic app routes reject them outright. Returned as code 'app_not_found' to avoid leaking the hidden backing app.","triggerScenarios":"Any generic app-management route decorated with @app_data_view that receives the app_id of a hidden workflow-only backing app behind a roster Agent (e.g. hitting /apps/{app_id}/... on the backing App rather than the Agent App).","commonSituations":"Frontend mistakenly targets the backing workflow app id instead of the agent app id; URL copy/paste of the wrong id from the database; tooling that lists all App rows hits the hidden one.","solutions":["Use the agent App id (the one shown in the console), not the hidden workflow-only backing app id.","Inspect AgentAppBinding to find the user-facing app id associated with the backing workflow.","Filter UI lists to exclude apps with a WORKFLOW_ONLY binding."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const app = await get(`/apps/${appId}`);\nif (app.agent_app_binding?.scope === 'workflow_only') {\n  // redirect to the user-facing agent app id instead\n}","typeGuard":null,"tryCatchPattern":"try {\n  await get(`/apps/${appId}/...`);\n} catch (e) {\n  if (e.code === 'app_not_found' && isAgentBackingAppId(appId)) {\n    // resolve and use the agent app id instead\n  } else { throw e; }\n}","preventionTips":["Never expose hidden workflow-only backing app ids in the UI; surface the agent app id.","Filter app lists to exclude apps whose AgentAppBinding.scope is WORKFLOW_ONLY."],"tags":["api","not-found","app","agent","rbac","decorator"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}