docker/cli · error

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

Error message

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

What it means

Returned by buildGenericResourceMap (generic_resource_opts.go:56) when a swarm.GenericResource in the parsed list has a nil DiscreteResourceSpec. After ParseGenericResources guarantees no NamedResourceSpec, buildGenericResourceMap expects every resource to be discrete; a resource that is neither named nor discrete violates that invariant and is rejected.

Solutions

  1. Update docker/cli and the daemon to matching versions to rule out parser drift.
  2. Re-check the --generic-resource input for empty or malformed entries.
  3. Report as a bug if it reproduces on current versions with valid `name=integer` input.

Example fix

// before: programmatic caller passes a GenericResource with nil DiscreteResourceSpec
res := swarm.GenericResource{} // both specs nil
// after
res := swarm.GenericResource{DiscreteResourceSpec: &swarm.DiscreteGenericResource{Kind: "GPU", Value: 2}}
Defensive patterns

Strategy: validation

Validate before calling

// For programmatic callers, ensure every resource has a discrete spec.
func allDiscrete(res []swarm.GenericResource) error {
    for _, r := range res {
        if r.DiscreteResourceSpec == nil {
            return fmt.Errorf("generic resource missing discrete spec: %+v", r)
        }
    }
    return nil
}

Type guard

// hasDiscreteSpec narrows resources safe for buildGenericResourceMap.
func hasDiscreteSpec(r swarm.GenericResource) bool { return r.DiscreteResourceSpec != nil }

Prevention

When it happens

Trigger: An internal/boundary condition where genericresource.Parse produced a GenericResource with both NamedResourceSpec and DiscreteResourceSpec nil. Not normally reachable from well-formed CLI input post-[378]; indicates a parser change or an empty/malformed resource slipped through.

Common situations: Version skew between docker/cli and moby/swarm genericresource parser, an empty entry that passed earlier checks, or programmatic callers constructing swarm.GenericResource structs directly.

Related errors


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

Appendix: source

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

	}

	for _, res := range swarmResources {
		if res.NamedResourceSpec != nil {
			return nil, fmt.Errorf("invalid generic-resource request `%s=%s`, Named Generic Resources is not supported for service create or update",
				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)

View on GitHub (pinned to 4f84911bfe)