You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On a fresh regenerated netdata-meta.db created by each binary
ARM64 (Oracle Cloud Ampere A1)
Root cause analysis
The bug is a boolean vs rc logic inversion between the PREPARE_STATEMENT macro and its caller sql_health_alarm_log2json:
PREPARE_STATEMENT (sqlite_functions.h) returns a boolean: _rc == SQLITE_OK → 1 on success, 0 on failure:
#definePREPARE_STATEMENT(db, sql, stmt_ptr) \
({ \
int _rc = simple_prepare_statement((db), (sql), stmt_ptr); \
if (_rc != SQLITE_OK) { \
internal_error(true, "Failed to prepare statement \"%s\", rc=%d in %s", (sql), _rc, __FUNCTION__); \
nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to prepare statement, rc=%d in %s", _rc, __FUNCTION__); \
} \
_rc == SQLITE_OK; \
})
sql_health_alarm_log2json (sqlite_health.c) treats the result as an SQLite rc and compares != SQLITE_OK (where SQLITE_OK == 0):
rc=PREPARE_STATEMENT(db_meta, buffer_tostring(command), &stmt_query);
...
if (unlikely(rc!=SQLITE_OK)) {
error_report("Failed to prepare statement SQL_SELECT_HEALTH_LOG");
return;
}
When the prepare succeeds, the macro returns 1, and 1 != 0 evaluates true → the code reports an error and returns an empty response. When the prepare actually fails, the macro returns 0, and the check passes → it continues with a NULL statement.
Expected behavior
/api/v1/alarm_log should return the stored alert history (the SQLite table health_log/health_log_detail is correctly populated — thousands of rows).
Steps to reproduce
Run any recent Netdata (stable 2.10.4 or nightly)
Wait for some alerts to be stored
curl http://localhost:19999/api/v1/alarm_log
Response is {} / empty, log shows Failed to prepare statement SQL_SELECT_HEALTH_LOG
Additional evidence
The exact SQL query works when executed directly against the same netdata-meta.db with system SQLite (3.46.1): returns rows correctly
PRAGMA integrity_check = ok, user_version = 18, table schemas match what the binary expects
The macro's own rc error message never appears (only the caller's unconditional error), confirming the prepare actually succeeds and the inversion is the culprit
Bug description
The
/api/v1/alarm_logendpoint always returns an empty response (HTTP 200, 0 bytes) on any recent Netdata version. The log shows:This happens with:
netdata/netdata:stablev2.10.4 (SQLite embedded 3.50.4)netdata/netdata:latestv2.10.0-980-nightly (SQLite embedded 3.53.3)netdata-meta.dbcreated by each binaryRoot cause analysis
The bug is a boolean vs rc logic inversion between the
PREPARE_STATEMENTmacro and its callersql_health_alarm_log2json:PREPARE_STATEMENT(sqlite_functions.h) returns a boolean:_rc == SQLITE_OK→1on success,0on failure:sql_health_alarm_log2json(sqlite_health.c) treats the result as an SQLite rc and compares!= SQLITE_OK(whereSQLITE_OK == 0):1, and1 != 0evaluates true → the code reports an error and returns an empty response. When the prepare actually fails, the macro returns0, and the check passes → it continues with a NULL statement.Expected behavior
/api/v1/alarm_logshould return the stored alert history (the SQLite tablehealth_log/health_log_detailis correctly populated — thousands of rows).Steps to reproduce
curl http://localhost:19999/api/v1/alarm_log{}/ empty, log showsFailed to prepare statement SQL_SELECT_HEALTH_LOGAdditional evidence
netdata-meta.dbwith system SQLite (3.46.1): returns rows correctlyPRAGMA integrity_check= ok,user_version= 18, table schemas match what the binary expects/api/v1/alarm_logis the intended endpoint for alert historyEnvironment