javan/whenever · error

[fail] Can only update, write or clear. Choose one.

Error message

[fail] Can only update, write or clear. Choose one.

What it means

whenever's three actions are mutually exclusive: --update-crontab (-i) merges into the existing crontab under the identifier, --write-crontab (-w) replaces the whole crontab, --clear-crontab (-c) removes the scheduled block. initialize counts how many of the three options were supplied and aborts with exit status 1 if more than one is present, because combining them (for example clear plus write) has no defined meaning. The bundled bin/whenever only sets each key when its flag is passed, so the count reflects actual flags.

Source

Thrown at lib/whenever/command_line.rb:24

      new(options).run
    end

    def initialize(options={})
      @options = options

      @options[:crontab_command] ||= 'crontab'
      @options[:file]            ||= 'config/schedule.rb'
      @options[:cut]             ||= 0
      @options[:identifier]      ||= default_identifier
      @options[:console]    = true if @options[:console].nil?

      if !File.exist?(@options[:file]) && @options[:clear].nil?
        warn("[fail] Can't find file: #{@options[:file]}")
        return_or_exit(false)
      end

      if [@options[:update], @options[:write], @options[:clear]].compact.length > 1
        warn("[fail] Can only update, write or clear. Choose one.")
        return_or_exit(false)
      end

      unless @options[:cut].to_s =~ /[0-9]*/
        warn("[fail] Can't cut negative lines from the crontab #{options[:cut]}")
        return_or_exit(false)
      end
      @options[:cut] = @options[:cut].to_i

      @timestamp = Time.now.to_s
    end

    def run
      if @options[:update] || @options[:clear]
        write_crontab(updated_crontab)
      elsif @options[:write]
        write_crontab(whenever_cron)
      else

View on GitHub (pinned to 756163ed1a)

Solutions

  1. Pick exactly one action: -i to install/refresh, -w to overwrite, -c to remove.
  2. If the goal is 'clear then reinstall', -i alone is enough — it atomically replaces the block marked by the identifier.
  3. In wrapper scripts, source the action from a single variable (e.g. ACTION=${WHENEVER_ACTION:--i}) instead of appending multiple flags.

Example fix

# before
whenever --update-crontab myapp --clear-crontab myapp

# after (update already replaces the prior block for this identifier)
whenever --update-crontab myapp
Defensive patterns

Strategy: validation

Validate before calling

actions = %i[update write clear].select { |a| opts[a] }
abort('choose exactly one of --update-crontab, --write-crontab, --clear-crontab') unless actions.size <= 1
Whenever::CommandLine.execute(opts)

Type guard

def single_action?(opts)
  %i[update write clear].count { |a| opts[a] } <= 1
end

Try / catch

begin
  Whenever::CommandLine.execute(opts)
rescue SystemExit => e
  abort('whenever rejected the flags; supply only one action flag') unless e.success?
end

Prevention

When it happens

Trigger: whenever -i -w; whenever --update-crontab myapp --clear-crontab myapp; any wrapper that concatenates flags from multiple sources, e.g. a hardcoded -i plus an env var that adds --clear-crontab, producing two or three actions in one command.

Common situations: Deploy scripts that evolved over time and gained a clear step before the install step; copy-pasted command lines mixing examples from different docs; deployment matrices where one flag comes from CI variables and another from the script itself.

Related errors


AI-assisted analysis of javan/whenever@756163ed1a (2026-08-21). Data as JSON: /api/errors/d69bdf8225e66f11. Report an issue: GitHub.