docker/cli · error

failed to create config

Error message

failed to create config %s: %w

What it means

Raised by createConfigs when a config does not exist yet (NotFound after ConfigInspect) and the ConfigCreate API call then fails. The wrapped %w carries the underlying daemon error (invalid name, oversized data, driver error).

Solutions

  1. Inspect the wrapped error for the daemon's reason.
  2. Ensure config names are valid ([a-zA-Z0-9_.-], <= 64 chars, lowercase recommended) and data <= 500KB.
  3. Retry the deploy; concurrent races resolve as an update next time.
  4. Verify the config file referenced in compose.yml exists and is readable.

Example fix

// before: referenced config file missing / too large
configs:
  big:
    file: ./large.bin   # > 500KB
// after: keep config data under 500KB
configs:
  big:
    file: ./small.txt
Defensive patterns

Strategy: validation

Validate before calling

// Validate config names and sizes before deploy
const maxConfigBytes = 500 * 1024
var validName = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9_.-]{0,63})$`)

func validateConfig(name string, data []byte, stackNS string) error {
    full := stackNS + "_" + name
    if !validName.MatchString(full) || len(full) > 64 {
        return fmt.Errorf("invalid config name %q", full)
    }
    if len(data) > maxConfigBytes {
        return fmt.Errorf("config %q too large: %d bytes", name, len(data))
    }
    return nil
}

Prevention

When it happens

Trigger: First-time deploy of a stack with configs defined in compose.yml, where ConfigCreate at deploy_composefile.go:159 fails. Also when a config is removed between Inspect and Create, producing a name collision.

Common situations: Config data exceeding the 500KB limit; invalid config name; concurrent deploy creating the same config; external config driver issues.

Related errors


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

Appendix: source

Thrown at cli/command/stack/deploy_composefile.go:163

		res, err := apiClient.ConfigInspect(ctx, configSpec.Name, client.ConfigInspectOptions{})
		switch {
		case err == nil:
			// config already exists, then we update that
			_, err := apiClient.ConfigUpdate(ctx, res.Config.ID, client.ConfigUpdateOptions{
				Version: res.Config.Meta.Version,
				Spec:    configSpec,
			})
			if err != nil {
				return fmt.Errorf("failed to update config %s: %w", configSpec.Name, err)
			}
		case errdefs.IsNotFound(err):
			// config does not exist, then we create a new one.
			_, _ = fmt.Fprintln(dockerCLI.Out(), "Creating config", configSpec.Name)
			_, err := apiClient.ConfigCreate(ctx, client.ConfigCreateOptions{
				Spec: configSpec,
			})
			if err != nil {
				return fmt.Errorf("failed to create config %s: %w", configSpec.Name, err)
			}
		default:
			return err
		}
	}
	return nil
}

func createNetworks(ctx context.Context, dockerCLI command.Cli, namespace convert.Namespace, networks map[string]client.NetworkCreateOptions) error {
	apiClient := dockerCLI.Client()

	existingNetworks, err := getStackNetworks(ctx, apiClient, namespace.Name())
	if err != nil {
		return err
	}

	existingNetworkMap := make(map[string]network.Summary)
	for _, nw := range existingNetworks.Items {

View on GitHub (pinned to 4f84911bfe)