hashicorp/terraform · error

error converting output values to json: %s

Error message

error converting output values to json: %s

What it means

Emitted by remoteClient.Put (backend_state.go:124-127) when json.Marshal cannot encode the already-marshaled output-values structure `ov` produced by jsonstate.MarshalOutputs. Since MarshalOutputs is designed to return JSON-serializable data, this is an extremely rare invariant violation — some value inside the structure is not JSON-serializable.

Source

Thrown at internal/backend/remote/backend_state.go:126

// Put the remote state.
func (r *remoteClient) Put(state []byte) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics
	ctx := context.Background()

	// Read the raw state into a Terraform state.
	stateFile, err := statefile.Read(bytes.NewReader(state))
	if err != nil {
		return diags.Append(fmt.Errorf("error reading state: %s", err))
	}

	ov, err := jsonstate.MarshalOutputs(stateFile.State.RootOutputValues)
	if err != nil {
		return diags.Append(fmt.Errorf("error reading output values: %s", err))
	}
	o, err := json.Marshal(ov)
	if err != nil {
		return diags.Append(fmt.Errorf("error converting output values to json: %s", err))
	}

	options := tfe.StateVersionUploadOptions{
		StateVersionCreateOptions: tfe.StateVersionCreateOptions{
			Lineage:          tfe.String(stateFile.Lineage),
			Serial:           tfe.Int64(int64(stateFile.Serial)),
			MD5:              tfe.String(fmt.Sprintf("%x", md5.Sum(state))),
			Force:            tfe.Bool(r.forcePush),
			JSONStateOutputs: tfe.String(base64.StdEncoding.EncodeToString(o)),
		},
		RawState: state,
	}

	// If we have a run ID, make sure to add it to the options
	// so the state will be properly associated with the run.
	if r.runID != "" {
		options.Run = &tfe.Run{ID: r.runID}
	}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Capture the wrapped %s error and the offending state, and file a bug against the jsonstate/state packages.
  2. Re-run the operation; if reproducible, bisect the config/provider producing the offending output value.
  3. As a workaround, simplify or temporarily remove output blocks whose values trigger the failure, then re-apply.
Defensive patterns

Strategy: try-catch

Try / catch

// Treat as invariant violation: capture the JSON error and the producing state for diagnostics.
ov, err := jsonstate.MarshalOutputs(stateFile.State.RootOutputValues)
if err != nil { return err }
o, err := json.Marshal(ov)
if err != nil {
    log.Printf("[ERROR] non-serializable output structure from MarshalOutputs: %v", err)
    return fmt.Errorf("error converting output values to json: %s", err)
}

Prevention

When it happens

Trigger: MarshalOutputs returns a structure containing a Go type that json.Marshal cannot serialize (e.g. a channel, func, or unsupported number), which should be impossible given MarshalOutputs' contract but would surface here.

Common situations: Effectively unreachable under normal operation; indicates a bug in jsonstate.MarshalOutputs or a corrupted state producing a non-serializable intermediate value. Almost always a code defect rather than a user config issue.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/d9ef45640d70f267. Report an issue: GitHub.