hashicorp/terraform · error
error reading state
Error message
error reading state: %s
What it means
First step of remoteClient.Put: parse the raw bytes Terraform hands it into a statefile.File. This is local parsing, not a network call. Failure means the bytes are not a recognizable Terraform state format — corruption or a version the parser can't read.
Solutions
- Inspect the state bytes: confirm it's JSON starting with {"version":...,"terraform_version":...}.
- Use a Terraform version that supports the state schema version in the file (check the 'version' field).
- Restore state from the last good TFC/TFE state version snapshot if locally corrupted.
- Avoid writing/pushing raw bytes from sources other than `terraform state pull`/`push`.
Defensive patterns
Strategy: validation
Validate before calling
// Validate bytes are JSON state before pushing
var head struct{ Version int `json:"version"` }
if err := json.Unmarshal(state, &head); err != nil { return fmt.Errorf("not JSON state: %w", err) } Type guard
func looksLikeJSONState(b []byte) bool {
var h struct{ Version int `json:"version"`; TerraformVersion string `json:"terraform_version"` }
return json.Unmarshal(b, &h) == nil && h.Version > 0
} Prevention
- Never hand-edit state JSON.
- Push state only via `terraform state push`.
- Don't downgrade Terraform across a state-format version boundary.
When it happens
Trigger: statefile.Read returns an error: the byte slice isn't valid JSON state (truncated, binary, plain text), the state 'version' field is higher than this build supports, or magic header/lineage fields are malformed.
Common situations: State was hand-edited or partially overwritten; downgrading Terraform across a state-format bump; a non-state file (e.g. plan output) was pointed at the state path; concurrent writers corrupted the in-memory buffer.
Related errors
- error reading output values
- Error checking remote Terraform version
- error converting output values to json
- Error downloading state
- Error retrieving state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/50d5cc0e89414a77.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote/backend_state.go:117
// 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))
}
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)),View on GitHub (pinned to d32a084675)