bytedance/deer-flow · error · ValueError

No models are authorized for the current role (authorization

Error message

No models are authorized for the current role (authorization provider error).

What it means

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.

Source

Thrown at backend/packages/harness/deerflow/agents/lead_agent/agent.py:193

    all_names = [m.name for m in app_config.models]

    # Check the resolved model against the action-scoped ``model:use`` policy.
    # This aligns with the Gateway ``get_model`` route, which also checks
    # ``authorize("model", "use")``. For the built-in RBAC provider (which
    # ignores ``action``) this is equivalent to a membership check; for a
    # custom provider that distinguishes ``list`` from ``use``, it prevents
    # a model visible via ``filter_resources`` but denied for ``use`` from
    # being silently selected at runtime.
    try:
        decision = provider.authorize(AuthzRequest(principal=principal, resource="model", action="use", target=model_name))
        if not isinstance(decision, AuthzDecision):
            raise TypeError("AuthorizationProvider.authorize must return AuthzDecision")
        if decision.allow:
            return model_name
    except Exception:
        logger.warning("Authorization provider failed while checking model:use for '%s'", model_name, exc_info=True)
        if authz_config.fail_closed:
            raise ValueError("No models are authorized for the current role (authorization provider error).")
        return model_name

    # Denied — graceful fallback: pick the first model that ``filter_resources``
    # says is visible AND that also passes ``authorize("model", "use")``. For the
    # built-in RBAC provider (which ignores ``action``) this is equivalent to
    # picking the first visible name; for a custom provider that distinguishes
    # ``list`` from ``use``, it ensures the fallback is actually usable.
    try:
        allowed_names = provider.filter_resources(principal, "model", all_names)
        if not isinstance(allowed_names, list) or any(not isinstance(n, str) for n in allowed_names):
            raise TypeError("AuthorizationProvider.filter_resources must return list[str]")
    except Exception:
        logger.warning("Authorization provider failed while resolving allowed models", exc_info=True)
        if authz_config.fail_closed:
            raise ValueError("No models are authorized for the current role (authorization provider error).")
        return model_name

    for candidate in allowed_names:

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Check Gateway logs: the warning immediately before this error logs the provider exception with traceback — fix that root cause.
  2. Restore/reach the authorization backend the provider depends on (service up, credentials valid).
  3. Ensure the custom provider's authorize() returns an AuthzDecision instance and never raises for normal deny paths.
  4. 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).

Example fix

# before
class MyProvider:
    def authorize(self, req):
        return self.remote.check(req)  # raises when remote is down

# after
class MyProvider:
    def authorize(self, req):
        decision = self.remote.check(req)  # may raise; wrap at boundary
        assert isinstance(decision, AuthzDecision)
        return decision
Defensive patterns

Strategy: try-catch

Validate before calling

# Health-check the provider at startup so fail_closed aborts don't surprise you mid-run
decision = provider.authorize(AuthzRequest(principal=test_principal, resource='model', action='use', target='__healthcheck__'))
assert isinstance(decision, AuthzDecision)

Type guard

from deerflow.authz import AuthzDecision
def provider_is_healthy(provider, principal) -> bool:
    try:
        return isinstance(provider.authorize(AuthzRequest(principal=principal, resource='model', action='use', target='x')), AuthzDecision)
    except Exception:
        return False

Try / catch

try:
    agent = create_agent(...)
except ValueError as e:
    if 'authorization provider error' in str(e):
        logger.error('authz backend unhealthy; run aborted by fail_closed')
        # surface to user as transient authz outage; page on-call, do not retry-loop
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/f934437e7642a5c1. Report an issue: GitHub.