gitlabhq/gitlabhq · error · Gitlab::Graphql::Errors::ArgumentError

No more than %{max_source_types} source work item types can

Error message

No more than %{max_source_types} source work item types can be provided at a time.

What it means

The `workItemTypesMoveTargets` resolver computes which target types a work item can move to, taking a required `sourceTypeIds` list capped at MAX_SOURCE_TYPES = 50. `ready?` raises ArgumentError (message interpolates the limit) when more than 50 source type global IDs are provided. The cap bounds the per-type move-target computation.

Source

Thrown at app/graphql/resolvers/work_items/move_targets_resolver.rb:40

      authorize :read_namespace

      MAX_SOURCE_TYPES = 50

      argument :source_full_path, GraphQL::Types::String,
        required: true,
        description: 'Full path of the source namespace. For example, `gitlab-org/gitlab-foss`.'

      argument :source_type_ids, [::Types::GlobalIDType[::WorkItems::Type]],
        required: true,
        description: <<~DESC.squish
          Global IDs of the source work item types to compute move targets for.
          A maximum of #{MAX_SOURCE_TYPES} IDs can be provided.
        DESC

      def ready?(**args)
        if args[:source_type_ids].size > MAX_SOURCE_TYPES
          raise Gitlab::Graphql::Errors::ArgumentError,
            format(
              _('No more than %{max_source_types} source work item types can be provided at a time.'),
              max_source_types: MAX_SOURCE_TYPES
            )
        end

        super
      end

      def resolve(source_full_path:, source_type_ids:)
        source_namespace = authorized_find!(full_path: source_full_path)

        ::WorkItems::Types::MoveTargetsService.new(
          current_user: current_user,
          source_namespace: source_namespace,
          target_namespace: object,
          source_type_ids: source_type_ids.map(&:model_id)
        ).execute

View on GitHub (pinned to 55ee20384a)

Solutions

  1. Send only the source type IDs you actually render (usually one or a handful), not the full catalog
  2. If genuinely needed, batch into groups of at most 50 IDs and merge results
  3. Cache the type list and intersect with what the UI offers before querying

Example fix

# before
const allTypeIds = (await client.request(WORK_ITEM_TYPES)).workItemTypes.nodes.map(n => n.id);
client.request(MOVE_TARGETS, { sourceFullPath, sourceTypeIds: allTypeIds }); // 67 ids -> error

# after
const needed = pickRelevantTypes(allTypeIds, selection);
client.request(MOVE_TARGETS, { sourceFullPath, sourceTypeIds: needed.slice(0, 50) });
Defensive patterns

Strategy: validation

Validate before calling

const MAX_SOURCE_TYPES = 50;
function assertSourceTypeIds(ids) {
  if (!Array.isArray(ids) || ids.length === 0 || ids.length > MAX_SOURCE_TYPES) {
    throw new Error(`sourceTypeIds must contain 1..${MAX_SOURCE_TYPES} global IDs`);
  }
  return ids;
}

Type guard

function isWithinSourceTypeLimit(ids) {
  return Array.isArray(ids) && ids.length <= 50;
}

Prevention

When it happens

Trigger: `workItemTypesMoveTargets(sourceFullPath: "gitlab-org/gitlab", sourceTypeIds: [51+ gids])`; clients that always send the complete list of type IDs fetched from `workItemTypes` for a large custom hierarchy instead of the subset in use.

Common situations: Self-managed instances with many custom work item types; admin tools that mirror every type into every request; code that fetched the full type list once and passes it wholesale without slicing.

Related errors


AI-assisted analysis of gitlabhq/gitlabhq@55ee20384a (2026-08-21). Data as JSON: /api/errors/f25cfd61547563f1. Report an issue: GitHub.