apache/superset · error · ValueError

user_id is required for private tasks

Error message

user_id is required for private tasks

What it means

Raised by TaskDAO.create_task (superset/daos/tasks.py) when scope is TaskScope.PRIVATE but user_id is None. Private tasks are keyed and deduplicated per user (get_active_dedup_key includes user_id), so an anonymous private task cannot be deduplicated or scoped; the DAO enforces the invariant with a ValueError before building the dedup key. Scope accepts either the TaskScope enum or its string value and normalizes both, but the user_id requirement applies regardless.

Source

Thrown at superset/daos/tasks.py:137

        already checked for existing tasks. Business logic (create vs join)
        is handled by SubmitTaskCommand.

        :param task_type: Type of task to create
        :param task_key: Task identifier (required)
        :param scope: Task scope (private/shared/system), defaults to private
        :param user_id: User ID creating the task
        :param payload: Optional user-defined context data (dict)
        :param properties: Optional framework-managed runtime state (e.g., timeout)
        :param kwargs: Additional task attributes (e.g., task_name)
        :returns: Created Task instance
        """
        # Handle both TaskScope enum and string values
        scope_value = scope.value if isinstance(scope, TaskScope) else scope
        scope_enum = scope if isinstance(scope, TaskScope) else TaskScope(scope)

        # Validate user_id is required for private tasks
        if scope_enum == TaskScope.PRIVATE and user_id is None:
            raise ValueError("user_id is required for private tasks")

        # Build dedup_key for active task
        dedup_key = get_active_dedup_key(
            scope=scope,
            task_type=task_type,
            task_key=task_key,
            user_id=user_id,
        )

        # Note: properties is handled separately via update_properties()
        task_data = {
            "task_type": task_type,
            "task_key": task_key,
            "scope": scope_value,
            "status": TaskStatus.PENDING.value,
            "dedup_key": dedup_key,
            **kwargs,
        }

View on GitHub (pinned to f4587218dd)

Solutions

  1. Pass user_id=get_user_id() (or the owning user's id) whenever creating a PRIVATE task.
  2. If the task is genuinely system-wide, use TaskScope.GLOBAL instead of PRIVATE.
  3. Validate scope/user_id pairing at the API boundary so callers get a 4xx, not a ValueError from the DAO.
  4. In celery contexts with no request, read the user from the trigger payload and pass it explicitly.

Example fix

# before
TaskDAO.create_task(scope=TaskScope.PRIVATE, task_type='alert', task_key=key)  # ValueError

# after
TaskDAO.create_task(
    scope=TaskScope.PRIVATE,
    task_type='alert',
    task_key=key,
    user_id=get_user_id(),  # required for PRIVATE scope
)
Defensive patterns

Strategy: validation

Validate before calling

from superset.daos.task import TaskScope  # adjust import path to actual enum home
from superset.utils.core import get_user_id

def validate_task_scope(scope: TaskScope, user_id: int | None) -> list[str]:
    errors = []
    if scope == TaskScope.PRIVATE and user_id is None:
        errors.append('user_id is required for private tasks')
    return errors

Type guard

def is_valid_private_task(scope: TaskScope, user_id: int | None) -> TypeGuard[bool]:
    return scope != TaskScope.PRIVATE or user_id is not None

Try / catch

try:
    task = TaskDAO.create_task(scope=scope, task_type=task_type, task_key=task_key, user_id=user_id)
except ValueError as err:
    if 'private tasks' in str(err):
        task = TaskDAO.create_task(scope=scope, task_type=task_type, task_key=task_key, user_id=get_user_id())

Prevention

When it happens

Trigger: Calling TaskDAO.create_task(scope='PRIVATE', task_type=..., task_key=..., user_id=None); background/command code that starts private tasks without threading the requesting user through; defaulting user_id to None in a new integration instead of g.user.id.

Common situations: New notification/alert execution paths or custom schedulers adopting the tasks framework and forgetting user propagation; refactors that drop user_id from kwargs; calling task creation outside a request context where user_id must be passed explicitly rather than derived.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/f8f4ad6aaf67dc51. Report an issue: GitHub.