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

This command was not invoked properly. The help for this com

Error message

This command was not invoked properly. The help for this command is
available below.

%{help}

What it means

`vagrant upload [options] <source> [destination] [name|id]` raises CLIInvalidUsage when the number of positional arguments is not 1-3: zero arguments, or four or more. The two-argument form auto-detects whether the second token is a guest name/id (matching an active machine) or a destination path, so anything outside that arity is rejected up front.

Source

Thrown at plugins/commands/upload/command.rb:54

            options[:compress] = true
          end
        end

        argv = parse_options(opts)
        return if !argv

        case argv.size
        when 3
          source, destination, guest = argv
        when 2, 1
          source = argv[0]
          if @env.active_machines.map(&:first).map(&:to_s).include?(argv[1])
            guest = argv[1]
          else
            destination = argv[1]
          end
        else
          raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp
        end

        # NOTE: We do this to handle paths on Windows like: "..\space dir\"
        # because the final separator acts to escape the quote and ends up
        # in the source value.
        source = source.sub(/["']$/, "")
        destination ||= File.basename(source)

        if File.file?(source)
          type = :file
        elsif File.directory?(source)
          type = :directory
        else
          raise Vagrant::Errors::UploadSourceMissing,
            source: source
        end

        with_target_vms(guest, single_target: true) do |machine|

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Use `vagrant upload <source> [destination] [name|id]` with 1-3 positional arguments
  2. On Windows, quote paths and avoid a trailing backslash immediately before the closing quote
  3. Run `vagrant upload -h` to re-check the argument layout

Example fix

# before
vagrant upload
vagrant upload dist/ /vagrant/dist web extra

# after
vagrant upload dist/ /vagrant/dist web
Defensive patterns

Strategy: validation

Validate before calling

positional = argv.reject { |a| a.start_with?('-') }
raise ArgumentError, 'usage: vagrant upload <source> [destination] [name|id]' unless (1..3).cover?(positional.size)
system('vagrant', 'upload', *positional)

Try / catch

begin
  VagrantPlugins::CommandUpload::Command.new(argv, env).execute
rescue Vagrant::Errors::CLIInvalidUsage => e
  warn e.extra_data[:help]
  exit 1
end

Prevention

When it happens

Trigger: `vagrant upload` with no source; `vagrant upload a b c d` (four positionals); Windows quoting where a trailing backslash escapes the closing quote and splits one path into extra tokens.

Common situations: Windows paths like `"..\dir\"` producing a stray token; scripts copying the 3-arg form plus an extra flag; forgetting the source while passing only destination and machine name.

Related errors


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