{"record":{"id":"fa393d680a4d0c54","repo":"langgenius/dify","slug":"not-found-fa393d","errorCode":null,"errorMessage":"Not Found","messagePattern":"Not Found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"api/controllers/console/flask_admission.py","lineNumber":59,"sourceCode":"                request_id=get_request_id(),\n                trace_id=get_trace_id() or request.headers.get(\"X-Trace-Id\"),\n            )\n            return view(self, request_context, *args, **kwargs)\n\n        admitted: Callable[Concatenate[T, P], R | Response] = inject_request_context\n        if require_valid_enterprise_license:\n            admitted = enterprise_license_required(admitted)\n        admitted = account_initialization_required(admitted)\n        admitted = login_required(admitted)\n        admitted = setup_required(admitted)\n\n        if editions is None:\n            return admitted\n\n        @wraps(view)\n        def enforce_edition(self: T, /, *args: P.args, **kwargs: P.kwargs) -> R | Response:\n            if dify_config.DEPLOYMENT_EDITION not in editions:\n                abort(404)\n            return admitted(self, *args, **kwargs)\n\n        return enforce_edition\n\n    return decorator\n","sourceCodeStart":41,"sourceCodeEnd":65,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/flask_admission.py#L41-L65","documentation":"HTTP 404 from `flask_admission.py`'s edition-enforcement wrapper. After stacking the auth decorators, if `editions` is provided and `dify_config.DEPLOYMENT_EDITION` is not in the allowed set, the `enforce_edition` wrapper calls `abort(404)` (default message). It deliberately returns 404 rather than 403 to avoid leaking which edition-only routes exist.","triggerScenarios":"Calling any console route decorated with an `editions=[...]` allowlist on a deployment whose `DEPLOYMENT_EDITION` is not in that list.","commonSituations":"Hitting an enterprise-only or cloud-only endpoint from a community/self-hosted deployment; edition mismatch after a license downgrade; misconfigured `DEPLOYMENT_EDITION` env var.","solutions":["Confirm `DEPLOYMENT_EDITION` matches the edition the route requires.","Upgrade/license the deployment to the required edition if the route is legitimately needed.","Do not expose edition-gated UI elements on deployments that lack that edition.","Treat the 404 as intentional — the route intentionally does not advertise its existence."],"exampleFix":"# before\nDEPLOYMENT_EDITION=SELF_HOSTED  # but route requires ENTERPRISE\n# after\nDEPLOYMENT_EDITION=ENTERPRISE  # with a valid enterprise license","handlingStrategy":"validation","validationCode":"from configs import dify_config\n\ndef edition_allowed(allowed: set[str]) -> bool:\n    return dify_config.DEPLOYMENT_EDITION in allowed\n\n# before calling an edition-gated route, confirm:\nif not edition_allowed({\"ENTERPRISE\"}):  # or whichever the route requires\n    ...","typeGuard":"ALLOWED_EDITIONS = {\"CLOUD\", \"ENTERPRISE\", \"SELF_HOSTED\", \"COMMUNITY\"}\ndef is_known_edition(v: str | None) -> bool:\n    return v in ALLOWED_EDITIONS","tryCatchPattern":"try:\n    resp = client.get(\"/some-edition-only-route\")\nexcept HTTPError as err:\n    if err.response.status_code == 404:\n        # edition mismatch — route intentionally not advertised\n        ...\n    raise","preventionTips":["Confirm DEPLOYMENT_EDITION matches the route's required edition.","Hide edition-gated UI elements on the wrong edition.","Treat the 404 as intentional — do not probe further.","Verify edition after a license change."],"tags":["edition","deployment-config","http-404","access-control"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}