kubernetes/kops · error

variable %q is both an array and a scalar

Error message

variable %q is both an array and a scalar

What it means

TerraformWriter.AddOutputVariableArray appends a literal to a Terraform output treated as an array. If the same key was already registered as a scalar output (Value != nil), the same output name would have to be both a scalar and an array, which Terraform cannot express, so kOps errors. It enforces one shape per output variable.

Source

Thrown at upup/pkg/fi/cloudup/terraformWriter/writer.go:202

		return fmt.Errorf("duplicate variable: %q", key)
	}
	t.outputs[key] = v

	return nil
}

func (t *TerraformWriter) AddOutputVariableArray(key string, literal *Literal) error {
	t.mutex.Lock()
	defer t.mutex.Unlock()

	if t.outputs[key] == nil {
		v := &terraformOutputVariable{
			Key: key,
		}
		t.outputs[key] = v
	}
	if t.outputs[key].Value != nil {
		return fmt.Errorf("variable %q is both an array and a scalar", key)
	}

	t.outputs[key].ValueArray = append(t.outputs[key].ValueArray, literal)

	return nil
}

func (t *TerraformWriter) GetDataSourcesByType() (map[string]map[string]interface{}, error) {
	dataSourcesByType := make(map[string]map[string]interface{})

	for _, dataSource := range t.dataSources {
		dataSources := dataSourcesByType[dataSource.DataType]
		if dataSources == nil {
			dataSources = make(map[string]interface{})
			dataSourcesByType[dataSource.DataType] = dataSources
		}

		tfName := sanitizeName(dataSource.DataName)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Locate the renderer adding the scalar with the same key and rename/namespace one of the two outputs.
  2. If patching kOps, choose a distinct key for the array output (e.g. key + "_list").
  3. Check for duplicated resources in the cluster spec triggering both code paths.
  4. Update kOps; shape collisions are internal bugs fixed upstream.

Example fix

// before
AddOutputVariable("vpc_id", lit)
AddOutputVariableArray("vpc_id", lit2) // conflicts
// after
AddOutputVariable("vpc_id", lit)
AddOutputVariableArray("vpc_ids", lit2)
Defensive patterns

Strategy: try-catch

Try / catch

if err := w.AddOutputVariableArray(key, lit); err != nil {
    if strings.Contains(err.Error(), "both an array and a scalar") {
        return fmt.Errorf("output %q shape conflict; rename array variant", key)
    }
    return err
}

Prevention

When it happens

Trigger: A renderer calls AddOutputVariableArray(key, ...) for a key that another renderer previously registered via AddOutputVariable(key, scalar). The mixed registration happens when two different features emit outputs with the same name but different shapes.

Common situations: kOps internal naming collision between a scalar output and an array output with identical names; patched/extended kOps adding an array output over an existing scalar name; duplicated render logic registering both forms.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/61532852471baae4. Report an issue: GitHub.