docker/compose · error

project name can't be empty. Use ProjectName option to set a

Error message

project name can't be empty. Use ProjectName option to set a valid name

What it means

After loading a project, postProcessProject asserts that a project name was resolved (from the `name:` field in the compose file, --project-name, COMPOSE_PROJECT_NAME, or the sanitized directory name). An empty name means labels and resource scoping would be broken, so Compose refuses to continue.

Source

Thrown at pkg/compose/loader.go:122

		// get compose file path set by COMPOSE_FILE
		cli.WithConfigFileEnv,
		// if none was selected, get default compose.yaml file from current dir or parent folder
		cli.WithDefaultConfigPath,
		// .. and then, a project directory != PWD maybe has been set so let's load .env file
		cli.WithEnvFiles(options.EnvFiles...), //nolint:gocritic // intentionally applying cli.WithEnvFiles twice.
		cli.WithDotEnv,                        //nolint:gocritic // intentionally applying cli.WithDotEnv twice.
		// eventually COMPOSE_PROFILES should have been set
		cli.WithDefaultProfiles(options.Profiles...),
		cli.WithName(options.ProjectName),
	)

	return cli.NewProjectOptions(options.ConfigPaths, append(options.ProjectOptionsFns, opts...)...)
}

// postProcessProject applies post-loading transformations to the project
func (s *composeService) postProcessProject(project *types.Project, options api.ProjectLoadOptions) (*types.Project, error) {
	if project.Name == "" {
		return nil, errors.New("project name can't be empty. Use ProjectName option to set a valid name")
	}

	project, err := project.WithServicesEnabled(options.Services...)
	if err != nil {
		return nil, err
	}

	// Add custom labels
	for name, s := range project.Services {
		s.CustomLabels = map[string]string{
			api.ProjectLabel:     project.Name,
			api.ServiceLabel:     name,
			api.VersionLabel:     api.ComposeVersion,
			api.WorkingDirLabel:  project.WorkingDir,
			api.ConfigFilesLabel: strings.Join(project.ComposeFiles, ","),
			api.OneoffLabel:      "False",
		}
		if len(options.EnvFiles) != 0 {

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Add `name: myproject` to the top of your compose file
  2. Pass `--project-name myproject` on the command line
  3. Export COMPOSE_PROJECT_NAME=myproject in the environment
  4. API users: set ProjectName in api.ProjectLoadOptions before calling the load API

Example fix

# before
services:
  web:
    image: nginx
# after
name: myproject
services:
  web:
    image: nginx
Defensive patterns

Strategy: validation

Validate before calling

# Go API: always set the project name explicitly before loading
opts := api.ProjectLoadOptions{
    ProjectName: "myproject", // or load from env
}
// CLI: ensure one name source exists
[ -n "$COMPOSE_PROJECT_NAME" ] || grep -q '^name:' compose.yaml || echo 'set a project name'

Prevention

When it happens

Trigger: cli.NewProjectOptions runs without any name source: no name: in the file, no ProjectName option, no COMPOSE_PROJECT_NAME, and no derivable directory name (e.g. reading config from stdin '-' with an empty/odd directory, or a directory name that sanitizes to empty such as '123' or non-alpha characters).

Common situations: Using the Go API with ProjectLoadOptions but forgetting ProjectName and loading from a reader; CI running compose with config piped via stdin; a project directory whose name starts with digits or contains only invalid chars after sanitization; COMPOSE_PROJECT_NAME set to empty string explicitly.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/2896c3033c3408b4. Report an issue: GitHub.