hashicorp/vagrant · error · Vagrant::Errors::PluginStateFileParseError

Failed to parse the state file "%{path}": %{message} Please

Error message

Failed to parse the state file "%{path}":
%{message}

Please remove the file and reinstall the plugins.
If this error recurs, please report a bug.

What it means

Vagrant::Plugin::StateFile reads the plugins state file (~/.vagrant.d/plugins.json, or a project-local .vagrant/plugins.json) and raises PluginStateFileParseError in initialize when the file exists but JSON.parse fails (lib/vagrant/plugin/state_file.rb:25). The file records which plugins are installed, so any truncation, stray comma, or non-JSON content breaks every plugin operation. As the message states, recovery is to remove the file and reinstall the plugins.

Source

Thrown at lib/vagrant/plugin/state_file.rb:25

module Vagrant
  module Plugin
    # This is a helper to deal with the plugin state file that Vagrant
    # uses to track what plugins are installed and activated and such.
    class StateFile

      # @return [Pathname] path to file
      attr_reader :path

      def initialize(path)
        @path = path

        @data = {}
        if @path.exist?
          begin
            @data = JSON.parse(@path.read)
          rescue JSON::ParserError => e
            raise Vagrant::Errors::PluginStateFileParseError,
              path: path, message: e.message
          end

          upgrade_v0! if !@data["version"]
        end

        @data["version"] ||= "1"
        @data["installed"] ||= {}
      end

      # Add a plugin that is installed to the state file.
      #
      # @param [String] name The name of the plugin
      def add_plugin(name, **opts)
        @data["installed"][name] = {
          "ruby_version"          => RUBY_VERSION,
          "vagrant_version"       => Vagrant::VERSION,
          "gem_version"           => opts[:version] || "",

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Validate the file to find the syntax error: `jq . ~/.vagrant.d/plugins.json` or `python -m json.tool` — fix the flagged spot or restore from backup
  2. Otherwise follow the message: rename/remove the file and reinstall the plugin set (capture `vagrant plugin list` first if it still runs, or replay your setup script)
  3. Simply deleting the file is safe — Vagrant regenerates an empty state file on the next plugin install
  4. Prevent recurrence: stop syncing VAGRANT_HOME during operations and never kill vagrant mid plugin command

Example fix

// before (~/.vagrant.d/plugins.json — broken JSON)
{"version": "1", "installed": {"vagrant-vbguest": {"ruby_version": "2.6.6",},}}

// after (valid)
{"version": "1", "installed": {"vagrant-vbguest": {"ruby_version": "2.6.6", "version": "0.30.0"}}}
Defensive patterns

Strategy: validation

Validate before calling

path = File.expand_path("~/.vagrant.d/plugins.json")
if File.exist?(path)
  begin
    JSON.parse(File.read(path))
  rescue JSON::ParserError => e
    abort "plugins.json is corrupt (#{e.message}); restore it before running vagrant"
  end
end

Try / catch

begin
  state_file = Vagrant::Plugin::StateFile.new(path)
rescue Vagrant::Errors::PluginStateFileParseError => e
  d = e.extra_data # {path:, message:}
  warn "corrupt state file #{d[:path]}: #{d[:message]}"
end

Prevention

When it happens

Trigger: Constructing StateFile.new(path) — which Vagrant does at startup for every plugin command — when the JSON at path is invalid: a write interrupted by killing the process mid `vagrant plugin install`, a hand edit that broke syntax, or a sync/merge tool writing conflict markers into the file.

Common situations: Syncing ~/.vagrant.d with cloud-sync tools that generate conflict files; CI images built by copying a half-written plugins.json; Windows editors adding a BOM or CRLF; two Vagrant versions writing the file concurrently.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21). Data as JSON: /api/errors/4ab550313b794ce3. Report an issue: GitHub.