opentofu/opentofu · info

empty value

Error message

empty value

What it means

Internal guard in genconfig's JSON-encode heuristic: the value is a known string but trims to zero length, so it cannot be JSON and is not wrapped in jsonencode(). The caller catches this and emits the empty string as plain HCL, making the error invisible in normal tofu usage.

Source

Thrown at internal/genconfig/generate_config.go:640

	tokens, err := wrapAsJSONEncodeFunctionCall(v)
	if err != nil {
		return hclwrite.TokensForValue(v)
	}
	return tokens
}

func wrapAsJSONEncodeFunctionCall(v cty.Value) (hclwrite.Tokens, error) {
	if v.IsNull() || v.Type() != cty.String || !v.IsKnown() {
		return nil, errors.New("value cannot be treated as JSON string")
	}

	// Don't let marked value to be passed into functions like AsString()
	// to prevent panics.
	v, _ = v.Unmark()

	s := []byte(strings.TrimSpace(v.AsString()))
	if len(s) == 0 {
		return nil, errors.New("empty value")
	}

	if s[0] != '{' && s[0] != '[' {
		return nil, errors.New("value is not a JSON object, nor a JSON array")
	}

	t, err := json.ImpliedType(s)
	if err != nil {
		return nil, fmt.Errorf("cannot define implied cty type (possibly not a JSON string): %w", err)
	}

	v, err = json.Unmarshal(s, t)
	if err != nil {
		return nil, fmt.Errorf("cannot unmarshal using implied type (possible not a JSON string): %w", err)
	}

	tokens := hclwrite.TokensForFunctionCall("jsonencode", hclwrite.TokensForValue(v))

View on GitHub (pinned to 3561785c48)

Solutions

  1. No action needed; fallback behavior is correct for empty strings
  2. When calling directly, pre-check strings.TrimSpace(s) != "" to avoid the sentinel error
Defensive patterns

Strategy: fallback

Validate before calling

v, _ = v.Unmark()
if strings.TrimSpace(v.AsString()) == "" {
    return hclwrite.TokensForValue(v) // skip jsonencode heuristic
}

Type guard

func isJSONEncodeCandidate(v cty.Value) bool {
    if v.IsNull() || !v.IsKnown() || !v.Type().Equals(cty.String) {
        return false
    }
    v, _ = v.Unmark()
    s := strings.TrimSpace(v.AsString())
    return len(s) > 0 && (s[0] == '{' || s[0] == '[')
}

Prevention

When it happens

Trigger: A known, non-null cty string value consisting solely of whitespace reaching wrapAsJSONEncodeFunctionCall. Only surfaced when the function is called directly rather than via tryWrapAsJsonEncodeFunctionCall.

Common situations: Extending or testing the generated-config feature; empty-string attributes in imported resources are simply emitted as "" with no jsonencode wrapper.

Related errors


AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15). Data as JSON: /api/errors/99bab479cd0af7b9. Report an issue: GitHub.