bkeepers/dotenv · error · ArgumentError

Invalid value for overwrite: #{overwrite.inspect}

Error message

Invalid value for overwrite: #{overwrite.inspect}

What it means

Dotenv.update accepts an `overwrite:` keyword that must be exactly `true`, `false`, or the symbol `:warn`; the case statement's else branch raises ArgumentError for any other value. dotenv deliberately does no type coercion, so truthy strings or integers are rejected instead of being interpreted. The raised message interpolates the offending value via inspect so you can immediately see what was passed.

Source

Thrown at lib/dotenv.rb:110

  end

  # Update `ENV` with the given hash of keys and values
  #
  # @param env [Hash] Hash of keys and values to set in `ENV`
  # @param overwrite [Boolean|:warn] Overwrite existing `ENV` values
  def update(env = {}, overwrite: false)
    instrument(:update) do |payload|
      diff = payload[:diff] = Dotenv::Diff.new do
        ENV.update(env.transform_keys(&:to_s)) do |key, old_value, new_value|
          # This block is called when a key exists. Return the new value if overwrite is true.
          case overwrite
          when :warn
            # not printing the value since that could be a secret
            warn "Warning: dotenv not overwriting ENV[#{key.inspect}]"
            old_value
          when true then new_value
          when false then old_value
          else raise ArgumentError, "Invalid value for overwrite: #{overwrite.inspect}"
          end
        end
      end
      diff.env
    end
  end

  # Modify `ENV` for the block and restore it to its previous state afterwards.
  #
  # Note that the block is synchronized to prevent concurrent modifications to `ENV`,
  # so multiple threads will be executed serially.
  #
  # @param env [Hash] Hash of keys and values to set in `ENV`
  def modify(env = {}, &block)
    SEMAPHORE.synchronize do
      diff = Dotenv::Diff.new
      update(env, overwrite: true)
      block.call

View on GitHub (pinned to 34156bf400)

Solutions

  1. Pass a real boolean or the symbol :warn: `overwrite: true`, `overwrite: false`, or `overwrite: :warn`
  2. Coerce external input before the call, e.g. `overwrite: %w[true 1 yes].include?(str.downcase)` or ActiveModel::Type::Boolean in Rails
  3. Use `opts.fetch(:overwrite, false)` instead of `opts[:overwrite]` so an absent key defaults to false rather than nil

Example fix

# before
Dotenv.update(env, overwrite: ENV["DOTENV_OVERWRITE"]) # "true" (String) -> ArgumentError

# after
Dotenv.update(env, overwrite: %w[true 1 yes].include?(ENV["DOTENV_OVERWRITE"].to_s.downcase))
Defensive patterns

Strategy: validation

Validate before calling

overwrite = opts.fetch(:overwrite, false)
raise ArgumentError, "overwrite must be true, false, or :warn" unless [true, false, :warn].include?(overwrite)
Dotenv.update(env, overwrite: overwrite)

Type guard

# Ruby: value-level guard for the overwrite flag
def valid_overwrite?(value)
  [true, false, :warn].include?(value)
end

Try / catch

begin
  Dotenv.update(env, overwrite: flag)
rescue ArgumentError
  flag = false # safe default, then retry with a known-good value
  retry
end

Prevention

When it happens

Trigger: `Dotenv.update({"KEY" => "v"}, overwrite: "true")` (String from ENV/ARGV/YAML), `overwrite: 1`, or `overwrite: nil` from `overwrite: opts[:overwrite]` when the options hash lacks the key — anything not literally true, false, or :warn.

Common situations: Reading the flag from `ENV["OVERWRITE"]` or CLI args and passing the string straight through; forwarding an optional options hash where a missing key yields nil; booleans serialized as strings in YAML/JSON config files.

Related errors


AI-assisted analysis of bkeepers/dotenv@34156bf400 (2026-08-21). Data as JSON: /api/errors/4dc5331867ec3fea. Report an issue: GitHub.