ytti/oxidized · error · ArgumentError

#{self.class.name}: configuration invalid: #{e.message}

Error message

#{self.class.name}: configuration invalid: #{e.message}

What it means

Oxidized calls validate_cfg! on every hook while loading the hooks section of the config, so this fires at startup, not at runtime. The exec hook checks that timeout (when present) is a positive Integer and that cmd (when present) is a String or an Array; any failed check is re-raised as ArgumentError with the prefix 'Exec: configuration invalid: <reason>' (lib/oxidized/hook/exec.rb:14-26). The original message ('invalid timeout value' or 'invalid cmd value') tells you which key failed.

Source

Thrown at lib/oxidized/hook/exec.rb:25

    @async = false
  end

  def validate_cfg!
    # Syntax check
    if cfg.has_key? "timeout"
      @timeout = cfg.timeout
      raise "invalid timeout value" unless @timeout.is_a?(Integer) &&
                                           @timeout.positive?
    end

    @async = !!cfg.async if cfg.has_key? "async"

    if cfg.has_key? "cmd"
      @cmd = cfg.cmd
      raise "invalid cmd value" unless @cmd.is_a?(String) || @cmd.is_a?(Array)
    end
  rescue RuntimeError => e
    raise ArgumentError,
          "#{self.class.name}: configuration invalid: #{e.message}"
  end

  def run_hook(ctx)
    env = make_env ctx
    logger.debug "Execute: #{@cmd.inspect}"
    th = Thread.new do
      run_cmd! env
    rescue StandardError => e
      raise e unless @async
    end
    th.join unless @async
  end

  def run_cmd!(env)
    pid = nil
    status = nil
    Timeout.timeout(@timeout) do

View on GitHub (pinned to 687ed4262d)

Solutions

  1. Set timeout to a positive integer, e.g. timeout: 60
  2. Make cmd a quoted string or a YAML list of strings: cmd: /usr/local/bin/notify.sh or cmd: ['/bin/notify.sh', '--event']
  3. Check indentation so timeout/cmd are keys of the exec hook block, not nested under another key
  4. Parse-check the file before restart: python3 -c 'import yaml; yaml.safe_load(open("/etc/oxidized/config"))' or ruby -ryaml -e 'p YAML.load_file(...)'

Example fix

# before
hooks:
  exec_hook:
    type: exec
    timeout: 60.0
    cmd:
      script: /usr/local/bin/notify.sh

# after
hooks:
  exec_hook:
    type: exec
    timeout: 60
    cmd: /usr/local/bin/notify.sh
Defensive patterns

Strategy: validation

Validate before calling

# validate the exec hook config before handing it to oxidized
cfg = { 'type' => 'exec', 'timeout' => 60, 'cmd' => '/usr/local/bin/notify.sh' }
raise ArgumentError, 'timeout must be a positive Integer' unless cfg['timeout'].is_a?(Integer) && cfg['timeout'].positive?
raise ArgumentError, 'cmd must be a String or Array' unless cfg['cmd'].is_a?(String) || cfg['cmd'].is_a?(Array)

Type guard

def valid_exec_hook_cfg?(cfg)
  cfg.is_a?(Hash) &&
    (cfg['timeout'].nil? || (cfg['timeout'].is_a?(Integer) && cfg['timeout'].positive?)) &&
    (cfg['cmd'].nil? || cfg['cmd'].is_a?(String) || cfg['cmd'].is_a?(Array))
end

Try / catch

begin
  Oxidized::Hook.load # or your hook registration entry point
rescue ArgumentError => e
  abort "refusing to start with invalid hook config: #{e.message}"
end

Prevention

When it happens

Trigger: Declaring a hook of type: exec whose block has timeout: 0, a negative number, a Float (60.0) or a quoted string ('60'), or a cmd: value that YAML parses into a Hash/number instead of a string or list (missing quote, block scalar, or wrong indentation under cmd:).

Common situations: Hand-edited YAML: float timeouts from templates, string numbers, or cmd written as a nested mapping. Copy-pasting hook examples with different indentation. Configs that worked before hooks gained strict validation.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


AI-assisted analysis of ytti/oxidized@687ed4262d (2026-08-23). Data as JSON: /api/errors/c71a6c9f150fc86e. Report an issue: GitHub.