Group.workItems with types: [EPIC] + assigneeUsernames returns empty nodes: [] for fine-grained PAT (classic PAT returns real data)

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Summary

Querying Group.workItems filtered to types: [EPIC] and assigneeUsernames returns an empty nodes: [] array when authenticated with a fine-grained personal access token, even when epics matching that filter genuinely exist and are assigned to the user. The same query with a classic read_api PAT returns the real, non-empty result set.

Unlike other known fine-grained PAT gaps (e.g. gitlab-org/gitlab#628840, which returns null for a single field), this failure is silent and easy to misread as "no matching epics" rather than a data-access gap, since GraphQL returns a valid, well-formed empty list rather than null or an error.

Steps to reproduce

  1. Create a fine-grained PAT scoped to a specific group, with at minimum: Work item: Read, Group: Read, Project: Read.

  2. Confirm (via the UI, or another read path) that the authenticated user has open epics assigned to them in that group.

  3. Run:

    query {
      group(fullPath: "<group-path>") {
        workItems(types: [EPIC], assigneeUsernames: ["<username>"], state: opened, first: 50) {
          nodes { iid title webUrl }
        }
      }
    }
  4. Observe nodes: [].

  5. Re-run the identical query with a classic read_api PAT for the same user/group and observe it returns the expected epics.

Expected behavior

The fine-grained PAT should return the same result set as the classic PAT when it has sufficient scope, matching the behavior already fixed for mergeRequestInteraction.reviewState in #628840 (closed).

Actual behavior

Fine-grained PAT: nodes: [] (false negative — reads as "no epics assigned"). Classic PAT: real, non-empty result set.

Impact

This is worse than a null-return gap because it produces no visible signal that data is missing — an empty array is indistinguishable from "the user truly has none," leading callers to silently under-report or skip results.

Edited by 🤖 GitLab Bot 🤖