docker/cli · error

duplicate generic-resource `%+v` for service task

Error message

duplicate generic-resource `%+v` for service task

What it means

Thrown by buildGenericResourceMap in generic_resource_opts.go:61 while constructing a map keyed by DiscreteResourceSpec.Kind. Generic resources are user-defined node resources (e.g. NVIDIA GPUs, Intel FPGAs) advertised on nodes and reserved by a service. The map enforces that each discrete resource Kind appears at most once in a service's reservation list; a second entry for the same Kind is rejected because it would be ambiguous.

Solutions

  1. Inspect current reservations with 'docker service inspect <svc>' and remove the duplicate Kind so each appears once.
  2. To request more of a discrete resource, increase the single value (e.g. '--generic-resource GPU=2') instead of repeating the flag.
  3. If updating, use '--generic-resource-rm GPU' first, then '--generic-resource-add GPU=<n>' to replace cleanly.

Example fix

// before
docker service create --name gpu --generic-resource GPU=1 --generic-resource GPU=2 nginx
// after
docker service create --name gpu --generic-resource GPU=2 nginx
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate that each generic-resource Kind appears once before calling ParseGenericResources / addGenericResources.
func uniqueGenericKinds(specs []string) error {
	seen := map[string]bool{}
	for _, s := range specs {
		k, _, ok := strings.Cut(s, "=")
		if !ok {
			return fmt.Errorf("missing '=' in %q", s)
		}
		k = strings.TrimSpace(k)
		if seen[k] {
			return fmt.Errorf("duplicate generic-resource %q for service task", k)
		}
		seen[k] = true
	}
	return nil
}

Prevention

When it happens

Trigger: Calling 'docker service create'/'docker service update' with multiple --generic-resource (alias --reserve-resource) flags resolving to the same Kind, e.g. '--generic-resource GPU=1 --generic-resource GPU=2'. Also fires during '--generic-resource-add' on update when the service already reserves that Kind, because addGenericResources merges new resources into the existing map.

Common situations: Copy-pasting resource flags; merging compose files that list a resource twice; scripting flag accumulation that appends rather than replaces; misunderstanding that a discrete resource is a single count rather than one flag per unit.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/ef8e54a13f5dda86. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/service/generic_resource_opts.go:61

				res.NamedResourceSpec.Kind, res.NamedResourceSpec.Value,
			)
		}
	}

	return swarmResources, nil
}

func buildGenericResourceMap(genericRes []swarm.GenericResource) (map[string]swarm.GenericResource, error) {
	m := make(map[string]swarm.GenericResource)

	for _, res := range genericRes {
		if res.DiscreteResourceSpec == nil {
			return nil, fmt.Errorf("invalid generic-resource `%+v` for service task", res)
		}

		_, ok := m[res.DiscreteResourceSpec.Kind]
		if ok {
			return nil, fmt.Errorf("duplicate generic-resource `%+v` for service task", res.DiscreteResourceSpec.Kind)
		}

		m[res.DiscreteResourceSpec.Kind] = res
	}

	return m, nil
}

func buildGenericResourceList(genericRes map[string]swarm.GenericResource) []swarm.GenericResource {
	l := make([]swarm.GenericResource, 0, len(genericRes))

	for _, res := range genericRes {
		l = append(l, res)
	}

	return l
}

View on GitHub (pinned to 4f84911bfe)