bug: splunk-hec-logging crashes with nil concatenation when error response json lacks text field
Maintainers usually reply within 5 days
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
Research direction
Read apisix/plugins/splunk-hec-logging.lua, especially send_to_splunk and the non-200 response handling around line 177. Check the plugin's existing tests and run the relevant test for Splunk HEC logging. Done means non-200 JSON responses without text return a useful error instead of crashing; the issue also flags handling failed JSON encoding in the batch-building loop.
Written by the indexing model from the issue text.
Description
Current Behavior
In apisix/plugins/splunk-hec-logging.lua, the send_to_splunk function handles non-200 responses from the Splunk HEC endpoint as follows:
if res.status ~= 200 then
local body = core.json.decode(res.body)
if not body then
return false, "failed to send splunk, http status code: " .. res.status
else
return false, "failed to send splunk, " .. body.text
end
end
When Splunk HEC (or any intermediate proxy / API gateway / reverse proxy in front of Splunk, such as an AWS ALB, Kong, Cloudflare, or NGINX ingress) returns an HTTP error status code (such as 400, 401, 403, 500, or 502) with a valid JSON payload that does not contain a text property (e.g. {"message": "Unauthorized"}, {"error": "Forbidden"}, {"code": 403}, or {}), core.json.decode(res.body) decodes into a Lua table (body ~= nil).
In the else block, body.text evaluates to nil, leading to string concatenation .. body.text. This throws an unhandled Lua runtime error:
attempt to concatenate field 'text' (a nil value).
This causes the batch processor background timer/worker to crash instead of cleanly returning false, err to handle retries and error logging.
Additionally, in send_to_splunk:
local t = {}
for _, e in ipairs(entries) do
table_insert(t, core.json.encode(e))
end
If core.json.encode(e) fails for any entry, it returns nil, err and inserts nil into t, resulting in corrupted batch payloads or issues on table_concat(t).
Expected Behavior
send_to_splunk should safely handle non-200 JSON responses where body.text is not present, falling back to other common error fields (like body.message or res.body or status code), rather than crashing with attempt to concatenate field 'text' (a nil value).
Error Logs
2026/10/07 08:30:00 [error] 51234#51234: *123456 [lua] batch-processor.lua:105: ...x/plugins/splunk-hec-logging.lua:177: attempt to concatenate field 'text' (a nil value), context: ngx.timer
stack traceback:
...x/plugins/splunk-hec-logging.lua:177: in function 'send_to_splunk'
.../apisix/utils/batch-processor.lua:100: in function 'batch_processor'
Steps to Reproduce
- Configure a route with the
splunk-hec-loggingplugin pointing to an endpoint that returns an error status code with JSON missingtext, for example HTTP 401{"message": "Unauthorized"}or HTTP 403{"error": "Forbidden"}. - Send requests through the route to generate log entries.
- When the batch processor flushes the batch to Splunk, observe the error log:
attempt to concatenate field 'text' (a nil value).
Environment
- APISIX version (run
apisix version): master (3.19.0) - Operating system (run
uname -a): Linux 5.15.0-generic x86_64 - OpenResty / Nginx version (run
openresty -Vornginx -V): openresty/1.25.3.1 - etcd version, if relevant (run
curl http://127.0.0.1:9090/v1/server_info): 3.5.11
- Dominant language
- Lua
- Stars
- 17.2k
- Forks
- 3k
- Avg merge
- 5d 48m
- Merged PRs (30d)
- 19
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from apache/apisix
-
As a user, I want the opa plugin to propagate trace context (traceparent) to OPA, so that OPA spans are linked to the APISIX request tracePossibly taken @GitNimay claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apache/apisix#14051 · 1 comment ·
Maintainers usually reply within 5 days
-
bug: tcp-logger attempts to send nil data and crashes when json encoding failsPossibly taken @bhuvan-somisetty claimed this 18 days ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 5 days
-
bug: datadog plugin drops service_name tag when service has no name configuredPossibly taken @bhuvan-somisetty claimed this 20 days ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 5 days
-
bug: syslog error messages run together with the underlying error (missing separator)Possibly taken @bhuvan-somisetty claimed this 30 days ago. Openbug
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 5 days
-
bug: syslog plugin crashes with nil-index error instead of returning an error when logger init failsPossibly taken @bhuvan-somisetty claimed this 33 days ago. Openbug
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 5 days
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
jangala-dev/devicecode-lua#344 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
luainkernel/lunatik#2018 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 86/100
LuaLS/lua-language-server#3481 ·
-
Kill Ishamuhale for Ishamuhale's FangPossibly taken A pull request linked to this issue is open or already merged. Openbug discord guide:04-the-barrens locale:enUS triage v0.2.6
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
Maintainers usually reply within 1 day