javan/whenever · warning
[fail] Can't cut negative lines from the crontab #{options[:
Error message
[fail] Can't cut negative lines from the crontab #{options[:cut]} What it means
The --cut/-k option strips N lines from the top of the existing crontab before updating (used to drop headers such as 'DO NOT EDIT THIS FILE'). The guard at command_line.rb:28-31 intends to reject negative cut values, but its regex /[0-9]*/ matches zero-or-more digits and therefore matches ANY string, including '-3' and the empty string — so as shipped this warning can never fire. Additionally, bin/whenever converts --cut to an Integer via lines.to_i before the check, so a negative value slips through and silently slices from the end of the crontab instead (split(...)[-3..-1] keeps the last 3 lines).
Source
Thrown at lib/whenever/command_line.rb:29
@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
puts Whenever.cron(@options)
puts "## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated."
puts "## [message] Run `whenever --help' for more options."
return_or_exit(true)
endView on GitHub (pinned to 756163ed1a)
Solutions
- Pass a non-negative integer to --cut / :cut (0 or more lines).
- Clamp computed values: use [0, computed_cut].max in the script that builds the command.
- If you maintain a fork, fix the guard to /\A\d+\z/ so invalid values are actually rejected instead of silently accepted.
Example fix
# before (goes negative on short crontabs) whenever --update-crontab -k $((total_lines - keep)) # after whenever --update-crontab -k $(( total_lines - keep > 0 ? total_lines - keep : 0 ))
Defensive patterns
Strategy: validation
Validate before calling
cut = Integer(value) rescue nil
abort('--cut must be a non-negative integer') unless cut && cut >= 0 Type guard
def valid_cut?(value) value.is_a?(Integer) && value >= 0 end
Try / catch
result = Whenever::CommandLine.execute(opts.merge(console: false))
abort('whenever rejected the cut option') unless result.zero? Prevention
- Clamp computed cut values with [0, computed].max before passing them to -k or :cut.
- Note the upstream guard at command_line.rb:28 never actually fires (its /[0-9]*/ regex matches every string), so validate on your side.
- In vendored or patched copies, tighten the regex to /\A\d+\z/ so invalid cut values fail loudly.
When it happens
Trigger: Computing the cut dynamically as (total_lines - lines_to_keep), which goes negative on short crontabs; passing user-supplied values to -k; running patched or vendored whenever builds where the regex was corrected to something like /\A\d+\z/, in which case cut: '-3' does trigger the warning and exit 1.
Common situations: Scripts migrating system crontabs (stripping the 3-line Debian 'DO NOT EDIT' header) where the line count assumption breaks; automation that derives cut from wc -l output; forks or vendor copies with a stricter guard than upstream.
Related errors
- [fail] Can't find file: #{@options[:file]}
- [fail] Can only update, write or clear. Choose one.
- :command, :path, & :flags are required
- You cannot specify an ':at' when using the shortcuts for tim
- Time must be in minutes or higher
AI-assisted analysis of javan/whenever@756163ed1a (2026-08-21).
Data as JSON: /api/errors/d88c7ddfbb00cc6a.
Report an issue: GitHub.