apache/beam · error

workerRegion and workerZone options are mutually exclusive

Error message

workerRegion and workerZone options are mutually exclusive

What it means

validateWorkerSettings rejects a configuration that sets both workerRegion and workerZone options. Dataflow placement must be either regional or zonal, not both; the two options are mutually exclusive.

Solutions

  1. Keep only one: drop --worker_zone to run regionally, or drop --worker_region and set --worker_zone for a specific zone.
  2. If regional is intended, ensure experiments do not add worker_region alongside a worker_zone (the experiment form is checked separately).
  3. Centralize placement options in one config source to avoid merging both.

Example fix

// before
// --worker_region=us-central1 --worker_zone=us-central1-a
// after
// --worker_zone=us-central1-a   (or --worker_region=us-central1)
Defensive patterns

Strategy: validation

Validate before calling

if opts.WorkerZone != "" && opts.WorkerRegion != "" {
    return fmt.Errorf("set only one of worker_region (%q) or worker_zone (%q)", opts.WorkerRegion, opts.WorkerZone)
}

Try / catch

if err := dataflowlib.ValidateWorkerSettings(ctx, opts); err != nil && strings.Contains(err.Error(), "mutually exclusive") {
    // decide placement: prefer worker_zone if both set
}

Prevention

When it happens

Trigger: JobOptions with WorkerZone != "" AND WorkerRegion != "" — e.g. --worker_region=us-central1 with --worker_zone=us-central1-a — during Translate.

Common situations: Combining a shared options file that sets worker_region with a per-job flag setting worker_zone; copy-paste from mixed documentation examples.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/cf42a93ebdb03c2a. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/runners/dataflow/dataflowlib/job.go:409

	addIfNonEmpty("machine_type", opts.MachineType)
	addIfNonEmpty("container_images", strings.Join(images, ","))
	addIfNonEmpty("temp_location", opts.TempLocation)

	for k, v := range opts.Options.Options {
		ret = append(ret, newDisplayData(k, "", "go_options", v))
	}
	return ret
}

func validateWorkerSettings(ctx context.Context, opts *JobOptions) error {
	if opts.Zone != "" && opts.WorkerRegion != "" {
		return errors.New("cannot use option zone with workerRegion; prefer either workerZone or workerRegion")
	}
	if opts.Zone != "" && opts.WorkerZone != "" {
		return errors.New("cannot use option zone with workerZone; prefer workerZone")
	}
	if opts.WorkerZone != "" && opts.WorkerRegion != "" {
		return errors.New("workerRegion and workerZone options are mutually exclusive")
	}

	hasExperimentWorkerRegion := false
	for _, experiment := range opts.Experiments {
		if strings.HasPrefix(experiment, "worker_region") {
			hasExperimentWorkerRegion = true
			break
		}
	}

	if hasExperimentWorkerRegion && opts.WorkerRegion != "" {
		return errors.New("experiment worker_region and option workerRegion are mutually exclusive")
	}
	if hasExperimentWorkerRegion && opts.WorkerZone != "" {
		return errors.New("experiment worker_region and option workerZone are mutually exclusive")
	}
	if hasExperimentWorkerRegion && opts.Zone != "" {
		return errors.New("experiment worker_region and option Zone are mutually exclusive")

View on GitHub (pinned to 12126d8942)