{"record":{"id":"f934437e7642a5c1","repo":"bytedance/deer-flow","slug":"no-models-are-authorized-for-the-current-role-aut","errorCode":null,"errorMessage":"No models are authorized for the current role (authorization provider error).","messagePattern":"No models are authorized for the current role \\(authorization provider error\\)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/lead_agent/agent.py","lineNumber":193,"sourceCode":"    all_names = [m.name for m in app_config.models]\n\n    # Check the resolved model against the action-scoped ``model:use`` policy.\n    # This aligns with the Gateway ``get_model`` route, which also checks\n    # ``authorize(\"model\", \"use\")``. For the built-in RBAC provider (which\n    # ignores ``action``) this is equivalent to a membership check; for a\n    # custom provider that distinguishes ``list`` from ``use``, it prevents\n    # a model visible via ``filter_resources`` but denied for ``use`` from\n    # being silently selected at runtime.\n    try:\n        decision = provider.authorize(AuthzRequest(principal=principal, resource=\"model\", action=\"use\", target=model_name))\n        if not isinstance(decision, AuthzDecision):\n            raise TypeError(\"AuthorizationProvider.authorize must return AuthzDecision\")\n        if decision.allow:\n            return model_name\n    except Exception:\n        logger.warning(\"Authorization provider failed while checking model:use for '%s'\", model_name, exc_info=True)\n        if authz_config.fail_closed:\n            raise ValueError(\"No models are authorized for the current role (authorization provider error).\")\n        return model_name\n\n    # Denied — graceful fallback: pick the first model that ``filter_resources``\n    # says is visible AND that also passes ``authorize(\"model\", \"use\")``. For the\n    # built-in RBAC provider (which ignores ``action``) this is equivalent to\n    # picking the first visible name; for a custom provider that distinguishes\n    # ``list`` from ``use``, it ensures the fallback is actually usable.\n    try:\n        allowed_names = provider.filter_resources(principal, \"model\", all_names)\n        if not isinstance(allowed_names, list) or any(not isinstance(n, str) for n in allowed_names):\n            raise TypeError(\"AuthorizationProvider.filter_resources must return list[str]\")\n    except Exception:\n        logger.warning(\"Authorization provider failed while resolving allowed models\", exc_info=True)\n        if authz_config.fail_closed:\n            raise ValueError(\"No models are authorized for the current role (authorization provider error).\")\n        return model_name\n\n    for candidate in allowed_names:","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/lead_agent/agent.py#L175-L211","documentation":"ValueError raised in _authorize_model_name when a custom AuthorizationProvider throws or returns a non-AuthzDecision during authorize('model','use') for the requested model, AND authz is configured fail_closed. Fail-closed means any provider malfunction is treated as a denial and the run aborts instead of silently using an unauthorized model.","triggerScenarios":"Agent creation with authz_config.fail_closed=true and an authorization provider that raises (network authz service down, bug in custom provider) or returns a wrong type when asked about model:use for the resolved model name.","commonSituations":"Custom authz provider calling an external policy service that is down/timing out; provider upgraded to a new return type; misconfigured fail_closed in config.yaml; RBAC provider misconfigured so every check throws.","solutions":["Check Gateway logs: the warning immediately before this error logs the provider exception with traceback — fix that root cause.","Restore/reach the authorization backend the provider depends on (service up, credentials valid).","Ensure the custom provider's authorize() returns an AuthzDecision instance and never raises for normal deny paths.","Only if the deployment accepts fail-open semantics: set the authz config to fail_open (understands the risk: a broken provider then lets model use through)."],"exampleFix":"# before\nclass MyProvider:\n    def authorize(self, req):\n        return self.remote.check(req)  # raises when remote is down\n\n# after\nclass MyProvider:\n    def authorize(self, req):\n        decision = self.remote.check(req)  # may raise; wrap at boundary\n        assert isinstance(decision, AuthzDecision)\n        return decision","handlingStrategy":"try-catch","validationCode":"# Health-check the provider at startup so fail_closed aborts don't surprise you mid-run\ndecision = provider.authorize(AuthzRequest(principal=test_principal, resource='model', action='use', target='__healthcheck__'))\nassert isinstance(decision, AuthzDecision)","typeGuard":"from deerflow.authz import AuthzDecision\ndef provider_is_healthy(provider, principal) -> bool:\n    try:\n        return isinstance(provider.authorize(AuthzRequest(principal=principal, resource='model', action='use', target='x')), AuthzDecision)\n    except Exception:\n        return False","tryCatchPattern":"try:\n    agent = create_agent(...)\nexcept ValueError as e:\n    if 'authorization provider error' in str(e):\n        logger.error('authz backend unhealthy; run aborted by fail_closed')\n        # surface to user as transient authz outage; page on-call, do not retry-loop\n    raise","preventionTips":["Monitor and alert on 'Authorization provider failed' warnings — they precede fail-closed aborts.","Keep the policy dependency highly available or consciously choose fail_open.","Unit-test custom providers: authorize() must return AuthzDecision and only raise on true malfunction."],"tags":["authz","config","provider","fail-closed","model"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}