ytti/oxidized · error · KeyError
hook.channel is required
Error message
hook.channel is required
What it means
The xmppdiff hook validates at startup that jid, password, channel and nick are all present; a missing channel raises KeyError 'hook.channel is required' (lib/oxidized/hook/xmppdiff.rb:46). The channel is the MUC room the hook joins; connect builds the MUC JID as cfg.channel + '/' + cfg.nick via Jabber::MUC::SimpleMUCClient#join, so it must be the full room JID, e.g. netdev@conference.example.com.
Source
Thrown at lib/oxidized/hook/xmppdiff.rb:46
end
rescue Timeout::Error
logger.info "timed out"
@client = nil
@muc = nil
end
@client.on_exception do
logger.info "XMPP connection aborted, reconnecting"
@client = nil
@muc = nil
connect
end
end
def validate_cfg!
raise KeyError, 'hook.jid is required' unless cfg.has_key?('jid')
raise KeyError, 'hook.password is required' unless cfg.has_key?('password')
raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
raise KeyError, 'hook.nick is required' unless cfg.has_key?('nick')
end
def run_hook(ctx)
return unless ctx.node
return unless ctx.event.to_s == "post_store"
begin
Timeout.timeout(15) do
gitoutput = ctx.node.output.new
diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
interesting = diff[:patch].lines.to_a[4..-1].any? do |line|
["+", "-"].include?(line[0]) && (not ["#", "!"].include?(line[1]))
end
if interesting
connect if @muc.nil?View on GitHub (pinned to 687ed4262d)
Solutions
- Add channel: netdev@conference.example.com (full MUC room JID) under the xmppdiff hook block
- Keep jid, password, channel, nick at the same indentation level
- Restart oxidized and confirm the log shows 'Joined <channel>'
Example fix
# before
hooks:
xmpp:
type: xmppdiff
jid: oxidized@xmpp.example.com
password: secret
nick: oxidized
# after
hooks:
xmpp:
type: xmppdiff
jid: oxidized@xmpp.example.com
password: secret
channel: netdev@conference.example.com
nick: oxidized Defensive patterns
Strategy: validation
Validate before calling
# check the xmppdiff block before oxidized loads it
hook_cfg = YAML.load_file('/etc/oxidized/config')['hooks']['xmpp']
missing = %w[jid password channel nick].reject { |k| hook_cfg.key?(k) }
raise ArgumentError, "xmppdiff config missing: #{missing.join(', ')}" unless missing.empty? Type guard
def xmppdiff_cfg_valid?(cfg)
cfg.is_a?(Hash) && %w[jid password channel nick].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
- Store channel as the full room JID (room@conference.example.com) to avoid runtime join failures
- Key-check all four xmppdiff keys in the config pipeline
- Smoke-test the MUC join with an XMPP client before rollout
When it happens
Trigger: A hooks block with type: xmppdiff that omits channel: (for example jid/password/nick were copied but the room was not), or a channel key lost to indentation or renamed to room.
Common situations: Copying a partial example; using a bare room name without the conference domain, which passes validation but fails to join at runtime; editing the hooks block and breaking indentation.
Related errors
- hook.nick is required
- hook.jid is required
- hook.password is required
- hook.remote_repo is required
- hook.token is required
AI-assisted analysis of ytti/oxidized@687ed4262d (2026-08-23).
Data as JSON: /api/errors/7af953e8b73b1779.
Report an issue: GitHub.