hashicorp/terraform · error · ErrInvalidRemotePlanFormat

invalid remote plan format, must be 1

Error message

invalid remote plan format, must be 1

What it means

ErrInvalidRemotePlanFormat is returned by LoadSavedPlanBookmark() when reading a saved-plan bookmark JSON file whose 'remote_plan_format' field is not 1. NewSavedPlanBookmark always writes 1; any other value (0, missing, or a future version) is treated as an incompatible/unknown bookmark format.

Source

Thrown at internal/cloud/cloudplan/saved_plan.go:13

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package cloudplan

import (
	"encoding/json"
	"errors"
	"io"
	"os"
	"strings"
)

var ErrInvalidRemotePlanFormat = errors.New("invalid remote plan format, must be 1")
var ErrInvalidRunID = errors.New("invalid run ID")
var ErrInvalidHostname = errors.New("invalid hostname")

type SavedPlanBookmark struct {
	RemotePlanFormat int    `json:"remote_plan_format"`
	RunID            string `json:"run_id"`
	Hostname         string `json:"hostname"`
}

func NewSavedPlanBookmark(runID, hostname string) SavedPlanBookmark {
	return SavedPlanBookmark{
		RemotePlanFormat: 1,
		RunID:            runID,
		Hostname:         hostname,
	}
}

func LoadSavedPlanBookmark(filepath string) (SavedPlanBookmark, error) {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Regenerate the plan file with the current terraform version: re-run 'terraform plan -out=<plan>'.
  2. Ensure you are not passing a non-plan JSON file where a plan bookmark is expected.
  3. Use a matching terraform version to consume a bookmark produced elsewhere.
Defensive patterns

Strategy: validation

Validate before calling

// Before loading a saved-plan bookmark, sanity-check the format version:
data, err := os.ReadFile(path)
if err != nil { return err }
var probe struct{ RemotePlanFormat int `json:"remote_plan_format"` }
if json.Unmarshal(data, &probe) == nil && probe.RemotePlanFormat != 1 {
    return fmt.Errorf("unsupported bookmark format %d, regenerate with this terraform", probe.RemotePlanFormat)
}

Try / catch

bm, err := cloudplan.LoadSavedPlanBookmark(path)
if err != nil {
    if errors.Is(err, cloudplan.ErrInvalidRemotePlanFormat) {
        // ask user to regenerate the plan with the current terraform version
        return err
    }
    return err
}

Prevention

When it happens

Trigger: Running 'terraform show' or apply on a plan file path that is actually a cloud/remote saved-plan bookmark whose JSON 'remote_plan_format' is missing or != 1 — e.g. a hand-edited or future-format bookmark, or a non-bookmark JSON file mistaken for one.

Common situations: Pointing terraform at a stale bookmark from a newer terraform version; passing an arbitrary JSON file as a plan; bookmark file corrupted/truncated so the field defaults to 0.

Related errors


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