hashicorp/terraform · error

error uploading state in compatibility mode: %v

Error message

error uploading state in compatibility mode: %v

What it means

Emitted by uploadStateFallback (backend_state.go:84-107), the compatibility path taken when the primary Upload returns tfe.ErrStateVersionUploadNotSupported (line 149). This path inline-encodes the state and calls StateVersions.Create, used for Terraform Enterprise v202306-1 and older. The error marks the compatibility upload itself as failed and sets r.stateUploadErr=true so the workspace is deliberately not unlocked afterward.

Source

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

		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),
		State:            tfe.String(base64.StdEncoding.EncodeToString(state)),
		JSONStateOutputs: tfe.String(base64.StdEncoding.EncodeToString(jsonStateOutputs)),
	}

	// 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}
	}

	// Create the new state.
	_, err := r.client.StateVersions.Create(ctx, r.workspace.ID, options)
	if err != nil {
		r.stateUploadErr = true
		return fmt.Errorf("error uploading state in compatibility mode: %v", err)
	}
	return err
}

// 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))

View on GitHub (pinned to c9def3e214)

Solutions

  1. Upgrade the TFE server past v202306-1 so the primary StateVersions.Upload path is used instead of the compatibility fallback.
  2. Check the wrapped %v cause — an MD5 mismatch indicates local state corruption; a 409/serial conflict indicates a concurrent writer holding a newer serial.
  3. Verify the token has 'State Versions: Create' permission on the workspace.
  4. Retry once after resolving the root cause; do not force-unlock until state is consistent.

Example fix

// before: TFE v202306-1, compatibility create fails with MD5 mismatch
Error: error uploading state in compatibility mode: state MD5 mismatch

// after: upgrade TFE to use native upload, or fix the corrupt local state
$ terraform state push <known-good-state>   # repair local state first
Defensive patterns

Strategy: validation

Validate before calling

// Detect server support up front so you can warn about legacy compatibility mode.
ep, err := r.client.AppliedIngressVersions.Read(ctx)
// (pseudographic) if server predates v202306-1, expect the fallback path and validate inputs.
if r.runID != "" {
    if _, err := r.client.Runs.Read(ctx, r.runID); err != nil {
        return fmt.Errorf("preflight: run %s invalid before compatibility upload: %w", r.runID, err)
    }
}

Try / catch

// Differentiate the not-supported diversion from a real compatibility failure.
_, err := r.client.StateVersions.Upload(ctx, r.workspace.ID, options)
if errors.Is(err, tfe.ErrStateVersionUploadNotSupported) {
    if ferr := r.uploadStateFallback(ctx, stateFile, state, o); ferr != nil {
        r.stateUploadErr = true
        return ferr // do NOT unlock; surface to operator
    }
}

Prevention

When it happens

Trigger: Running against an old TFE server that does not support the modern state upload endpoint, AND the legacy StateVersions.Create call fails (MD5 mismatch, size limit, permission to create state versions, lineage/serial conflict, network).

Common situations: Pinned legacy TFE version; migration/upgrade window where server is mid-deploy; workspace with a state serial that conflicts; restricted permissions on the service account; corporate proxy mangling the large inline base64 payload.

Related errors


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