apache/beam · error

error reading --label flag as JSON

Error message

error reading --label flag as JSON

What it means

getJobOptions in the Dataflow runner parses the --label command-line flag as a JSON object mapping label keys to values. If json.Unmarshal of the flag's contents fails, the error is wrapped with this message and returned, aborting job option construction. Labels must be valid JSON of the form {"key":"value"}.

Source

Thrown at sdks/go/pkg/beam/runners/dataflow/dataflow.go:287

func getJobOptions(ctx context.Context, streaming bool) (*dataflowlib.JobOptions, error) {
	project := gcpopts.GetProjectFromFlagOrEnvironment(ctx)
	if project == "" {
		return nil, errors.New("no Google Cloud project specified. Use --project=<project>")
	}
	region := gcpopts.GetRegion(ctx)
	if region == "" {
		return nil, errors.New("no Google Cloud region specified. Use --region=<region>. See https://cloud.google.com/dataflow/docs/concepts/regional-endpoints")
	}
	if *stagingLocation == "" {
		return nil, errors.New("no GCS staging location specified. Use --staging_location=gs://<bucket>/<path>")
	}

	checkSoftDeletePolicyEnabled(ctx, *stagingLocation, "staging_location")

	var jobLabels map[string]string
	if *labels != "" {
		if err := json.Unmarshal([]byte(*labels), &jobLabels); err != nil {
			return nil, errors.Wrapf(err, "error reading --label flag as JSON")
		}
	}

	if *cpuProfiling != "" {
		perf.EnableProfCaptureHook("gcs_profile_writer", *cpuProfiling)
	}

	if *autoscalingAlgorithm != "" {
		if *autoscalingAlgorithm != "NONE" && *autoscalingAlgorithm != "THROUGHPUT_BASED" {
			return nil, errors.New("invalid autoscaling algorithm. Use --autoscaling_algorithm=(NONE|THROUGHPUT_BASED)")
		}
	}

	if *flexRSGoal != "" {
		switch *flexRSGoal {
		case "FLEXRS_UNSPECIFIED", "FLEXRS_SPEED_OPTIMIZED", "FLEXRS_COST_OPTIMIZED":
			// valid values
		default:

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass the --label flag as a valid JSON object, e.g. --label='{"env":"prod","team":"data"}'
  2. Validate the JSON locally with `echo '<value>' | jq .` before launching
  3. Check shell quoting: wrap the JSON in single quotes so double quotes survive
  4. If no labels are needed, omit the flag entirely (empty string is skipped)

Example fix

// before
--label=env=prod,team=data
// after
--label='{"env":"prod","team":"data"}'
Defensive patterns

Strategy: validation

Validate before calling

if labels != "" {
    var m map[string]string
    if err := json.Unmarshal([]byte(labels), &m); err != nil {
        return fmt.Errorf("--label flag is not valid JSON: %w", err)
    }
}

Try / catch

if err := run(); err != nil {
    if strings.Contains(err.Error(), "--label flag") {
        log.Fatalf("fix --label JSON: %v", err)
    }
}

Prevention

When it happens

Trigger: Launching a Dataflow pipeline with a non-empty --label flag whose value is not valid JSON (e.g. single quotes, unquoted keys, trailing commas, or a plain key=value string).

Common situations: Shell quoting issues where single-quoted JSON is passed but interpreted incorrectly, users passing key=value pairs instead of a JSON object, copying labels from documentation with markdown quotes, or CI variables containing escaped quotes.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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