This page is built from reading the Wazuh 4.14.7 source and the public documentation, not from a run on our side. The Limits section says exactly what that covers.
How to check in one minute
The message goes to the active response log of the host where the response ran, the agent or the manager depending on <location>:
grep "Cannot read 'srcip'" /var/ossec/logs/active-responses.log | tail -n 5
Then look at what triggers the response. On the manager:
grep -A8 '<active-response>' /var/ossec/etc/ossec.conf
If it is bound by <level> or <rules_group>, it runs for every matching rule, including rules whose events carry no IP. This lists, per rule ID, the alerts in today's alerts.json that have neither data.srcip nor a Windows ipAddress / destinationIp:
python3 - <<'EOF'
import json, collections
n = collections.Counter()
for line in open('/var/ossec/logs/alerts/alerts.json'):
try:
a = json.loads(line)
except ValueError:
continue
d = a.get('data') if isinstance(a.get('data'), dict) else {}
w = d.get('win') if isinstance(d.get('win'), dict) else {}
e = w.get('eventdata') if isinstance(w.get('eventdata'), dict) else {}
if not ({'srcip'} & d.keys() or {'ipAddress', 'destinationIp'} & e.keys()):
n[a.get('rule', {}).get('id')] += 1
for rule_id, count in n.most_common(20):
print(rule_id, count)
EOF
Any rule ID in that list that also matches your active response binding will produce this message.
Why it happens
In 4.14.7 the response reads the source IP with get_srcip_from_json() in src/active-response/active_responses.c. Reading the code, it does this, in order:
- It needs
parameters.alert.datain its input to be an object. If not, there is no IP. - If
data.win.eventdata.ipAddressis a string, that is the candidate. If not, it triesdata.win.eventdata.destinationIp. - Only if neither Windows field is a string does it read
data.srcip. - The candidate must parse as an IPv4 or IPv6 address. If it does not, there is no IP. There is no fall-back to the next field.
When nothing comes back, firewalls/default-firewall-drop.c writes this line to logs/active-responses.log under the install directory and exits with an error:
Cannot read 'srcip' from data or invalid IP format
In 4.14.7 the text ends with or invalid IP format. Public reports, for example wazuh/wazuh issue 11842, quote the shorter form used in the title of this page.
So there are three practical causes:
- The event has no
srcip. The decoder for that source does not extract one, or it lands under another name. The JSON decoder keeps the key's own name (we saw this inwazuh-logteston 4.14.7 with Nextcloud and Office 365 events), so an address under a key such assrc_ipbecomesdata.src_ip, which this function does not read. - The field exists but is not an IP address, for example a host name.
- Windows events: if
win.eventdata.ipAddressis present as a string but is not a valid address, the function returns nothing without tryingdestinationIpordata.srcip.
What it means for rules that use srcip
The message does not mean your rule failed. The rule matched, the alert was written, and only the response step found nothing to act on. But the same decoded field feeds rules: in the Wazuh decoder documentation srcip is one of the static fields, alongside srcuser, dstip, action, status and others. If a source never decodes srcip, rules that rely on it for that source have nothing to read either.
One measured point about static fields: on 4.14.7 we referenced the static field status as <field name="status"> in a rule. wazuh-analysisd -t failed with Failure to read rule 44732. Field 'status' is static and a CRITICAL (1220), and the manager would not start. The static tag <status> loaded cleanly. srcip is in the same static list; we have not run that exact case for srcip. In rules, use the <srcip> option, not <field name="srcip">.
Fix
1. Bind the response only to rules whose events carry an address. Use <rules_id>, which the documentation describes as limiting the command to when the listed rules fire, instead of a level or group that also catches rules without an IP:
<active-response>
<command>firewall-drop</command>
<location>local</location>
<rules_id>100100</rules_id> <!-- your rule ID(s) -->
<timeout>600</timeout>
</active-response>
2. Make the decoder name the field srcip for the sources you want to block on. For a regex decoder, <order> maps each capture group to a field name, and srcip is one of the names it accepts. Test the decoder with wazuh-logtest and confirm srcip appears in the decoding phase before relying on the response.
3. Check the value is an address. If the field holds a host name or a placeholder, the response cannot use it, whatever the binding.
Limits of what we measured
What this page says about the message comes from reading the 4.14.7 source (active_responses.c, active_responses.h, firewalls/default-firewall-drop.c) and the public documentation. We have not triggered the message on a running agent or manager, have not tested Windows events, and have not measured which releases print the shorter text. The Python check above is a plain reader of alerts.json; it does not know your active response binding. The one measured item is the static-field load failure, and we measured it for status, not for srcip.