{"record":{"id":"c71a6c9f150fc86e","repo":"ytti/oxidized","slug":"self-class-name-configuration-invalid-e-mes","errorCode":null,"errorMessage":"#{self.class.name}: configuration invalid: #{e.message}","messagePattern":"#(.+?): configuration invalid: #(.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/oxidized/hook/exec.rb","lineNumber":25,"sourceCode":"    @async = false\n  end\n\n  def validate_cfg!\n    # Syntax check\n    if cfg.has_key? \"timeout\"\n      @timeout = cfg.timeout\n      raise \"invalid timeout value\" unless @timeout.is_a?(Integer) &&\n                                           @timeout.positive?\n    end\n\n    @async = !!cfg.async if cfg.has_key? \"async\"\n\n    if cfg.has_key? \"cmd\"\n      @cmd = cfg.cmd\n      raise \"invalid cmd value\" unless @cmd.is_a?(String) || @cmd.is_a?(Array)\n    end\n  rescue RuntimeError => e\n    raise ArgumentError,\n          \"#{self.class.name}: configuration invalid: #{e.message}\"\n  end\n\n  def run_hook(ctx)\n    env = make_env ctx\n    logger.debug \"Execute: #{@cmd.inspect}\"\n    th = Thread.new do\n      run_cmd! env\n    rescue StandardError => e\n      raise e unless @async\n    end\n    th.join unless @async\n  end\n\n  def run_cmd!(env)\n    pid = nil\n    status = nil\n    Timeout.timeout(@timeout) do","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/ytti/oxidized/blob/687ed4262d9d21e54662e872e2383386d8498f7b/lib/oxidized/hook/exec.rb#L7-L43","documentation":"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.","triggerScenarios":"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:).","commonSituations":"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.","solutions":["Set timeout to a positive integer, e.g. timeout: 60","Make cmd a quoted string or a YAML list of strings: cmd: /usr/local/bin/notify.sh or cmd: ['/bin/notify.sh', '--event']","Check indentation so timeout/cmd are keys of the exec hook block, not nested under another key","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(...)'"],"exampleFix":"# before\nhooks:\n  exec_hook:\n    type: exec\n    timeout: 60.0\n    cmd:\n      script: /usr/local/bin/notify.sh\n\n# after\nhooks:\n  exec_hook:\n    type: exec\n    timeout: 60\n    cmd: /usr/local/bin/notify.sh","handlingStrategy":"validation","validationCode":"# validate the exec hook config before handing it to oxidized\ncfg = { 'type' => 'exec', 'timeout' => 60, 'cmd' => '/usr/local/bin/notify.sh' }\nraise ArgumentError, 'timeout must be a positive Integer' unless cfg['timeout'].is_a?(Integer) && cfg['timeout'].positive?\nraise ArgumentError, 'cmd must be a String or Array' unless cfg['cmd'].is_a?(String) || cfg['cmd'].is_a?(Array)","typeGuard":"def valid_exec_hook_cfg?(cfg)\n  cfg.is_a?(Hash) &&\n    (cfg['timeout'].nil? || (cfg['timeout'].is_a?(Integer) && cfg['timeout'].positive?)) &&\n    (cfg['cmd'].nil? || cfg['cmd'].is_a?(String) || cfg['cmd'].is_a?(Array))\nend","tryCatchPattern":"begin\n  Oxidized::Hook.load # or your hook registration entry point\nrescue ArgumentError => e\n  abort \"refusing to start with invalid hook config: #{e.message}\"\nend","preventionTips":["Template hook configs that already pass validate_cfg! and only substitute values","YAML-lint and key-check the hooks section in CI before deploying to the oxidized host","Use plain integers for timeout and quote cmd strings"],"tags":["oxidized","exec-hook","config-validation","yaml","argumenterror"],"backgroundTag":"config-validation-failed","analyzedSha":"687ed4262d9d21e54662e872e2383386d8498f7b","analyzedAt":"2026-08-23T11:19:42.084Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}