semaphoreui/semaphore · error

values must be scalar

Error message

values must be scalar

What it means

When mustValuesBeScalar is true, validateJSON rejects environment JSON objects whose values are arrays or nested objects. Environment variables must be flat scalar strings so they can be exported directly into the job's process environment; complex structures are not representable as env vars.

Solutions

  1. Flatten nested objects into scalar keys (e.g. CFG_A: "1") before submitting
  2. Serialize complex values to a string (JSON/base64) and store as a single scalar variable
  3. Store complex config in a file/repository artifact or a secret instead of environment variables

Example fix

// before
{"DB": {"host": "localhost", "port": 5432}}
// after
{"DB_HOST": "localhost", "DB_PORT": "5432"}
Defensive patterns

Strategy: validation

Validate before calling

for k, v := range payload {
	switch v.(type) {
	case []any, map[string]any:
		return fmt.Errorf("env var %s must be scalar", k)
	}
}

Type guard

func allScalars(m map[string]any) bool {
	for _, v := range m {
		switch v.(type) {
		case []any, map[string]any:
			return false
		}
	}
	return true
}

Try / catch

if err := env.Validate(); err != nil {
	if strings.Contains(err.Error(), "values must be scalar") {
		return fmt.Errorf("environment rejected: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Environment payload like {"CFG": {"a": 1}} or {"LIST": [1,2]} submitted where scalar-only values are enforced (validated by Validate on environment create/update).

Common situations: Users pasting nested JSON config blobs as environment variables; tools serializing maps/lists of settings into the env payload; migrating from another CI that allows nested env values.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/2203b02dd1a72c65. Report an issue: GitHub.

Appendix: source

Thrown at db/Environment.go:100

	if s == "" {
		return nil
	}

	var data map[string]any
	err := json.Unmarshal([]byte(s), &data)
	if err != nil {
		return errors.New("must be valid JSON")
	}

	for k, v := range data {
		if k == "" {
			return errors.New("key can not be empty")
		}

		if mustValuesBeScalar {
			switch v.(type) {
			case []any, map[string]any:
				return errors.New("values must be scalar")
			}
		}
	}

	return nil
}

func (env *Environment) Validate() (err error) {
	if env.Name == "" {
		err = common_errors.NewValidationError("Environment name can not be empty")
		return
	}

	err = validateJSON(env.JSON, false)
	if err != nil {
		err = common_errors.NewValidationError("Extra variables " + err.Error())
		return
	}

View on GitHub (pinned to 1774ccb71a)