ytti/oxidized · error · KeyError

hook.token is required

Error message

hook.token is required

What it means

The slackdiff hook validates at startup that both token and channel keys exist in its config; a missing token raises KeyError 'hook.token is required' (lib/oxidized/hook/slackdiff.rb:10) while hooks load, aborting startup. The token is a Slack API token (xoxb-... bot or xoxp-... user token) that slack_ruby_client uses for auth_test, snippet upload, and chat.postMessage.

Source

Thrown at lib/oxidized/hook/slackdiff.rb:10

require 'slack_ruby_client'
require 'uri'
require 'net/http'

# defaults to posting a diff, if messageformat is supplied them a message will be posted too
# diff defaults to true

class SlackDiff < Oxidized::Hook
  def validate_cfg!
    raise KeyError, 'hook.token is required' unless cfg.has_key?('token')
    raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
  end

  def slack_upload(client, title, content, channel, proxy)
    logger.info "Posting diff as snippet to #{channel}"
    upload_dest = client.files_getUploadURLExternal(filename:     "change",
                                                    length:       content.length,
                                                    snippet_type: "diff")
    file_uri = URI.parse(upload_dest[:upload_url])

    proxy_uri = URI.parse(proxy) if proxy
    proxy_address = proxy_uri ? proxy_uri.host : :ENV
    proxy_port = proxy_uri&.port
    proxy_user = proxy_uri&.user
    proxy_pass = proxy_uri&.password

    http = Net::HTTP.new(file_uri.host, file_uri.port, proxy_address, proxy_port, proxy_user, proxy_pass)
    http.use_ssl = true

View on GitHub (pinned to 687ed4262d)

Solutions

  1. Add the token under the slackdiff hook block: token: xoxb-1234-abcdef (inject it from your secrets manager at deploy time, do not commit it)
  2. Confirm both token and channel sit at the same indentation as the hook's other keys
  3. Restart oxidized so hook validation runs again

Example fix

# before
hooks:
  slack:
    type: slackdiff
    channel: "#netdev-changes"

# after
hooks:
  slack:
    type: slackdiff
    token: xoxb-1234567890-abcdef
    channel: "#netdev-changes"
Defensive patterns

Strategy: validation

Validate before calling

# check the slackdiff block before oxidized loads it
hook_cfg = YAML.load_file('/etc/oxidized/config')['hooks']['slack']
missing = %w[token channel].reject { |k| hook_cfg.key?(k) }
raise ArgumentError, "slackdiff config missing: #{missing.join(', ')}" unless missing.empty?

Type guard

def slackdiff_cfg_valid?(cfg)
  cfg.is_a?(Hash) && %w[token channel].all? { |k| cfg[k].is_a?(String) && !cfg[k].empty? }
end

Try / catch

begin
  hook.validate_cfg!
rescue KeyError => e
  abort "fix the hooks config: #{e.message}"
end

Prevention

When it happens

Trigger: A hooks block with type: slackdiff that lacks token: (only channel set), or a token key that is misspelled or indented so it never lands in the hook's cfg hash.

Common situations: Copying the slackdiff example and forgetting the secret; intending to inject the token from an env var or secret store but leaving the literal key out of the deployed config; YAML indentation errors after adding messageformat or proxy keys.

Related errors


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