Skip to content

[Bug]: /api/v1/alarm_log always empty - boolean vs rc logic inversion in PREPARE_STATEMENT caller #23364

Description

@manuveranavarro

Bug description

The /api/v1/alarm_log endpoint always returns an empty response (HTTP 200, 0 bytes) on any recent Netdata version. The log shows:

Failed to prepare statement SQL_SELECT_HEALTH_LOG

This happens with:

  • netdata/netdata:stable v2.10.4 (SQLite embedded 3.50.4)
  • netdata/netdata:latest v2.10.0-980-nightly (SQLite embedded 3.53.3)
  • 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:

  1. PREPARE_STATEMENT (sqlite_functions.h) returns a boolean: _rc == SQLITE_OK1 on success, 0 on failure:
#define PREPARE_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; \
    })
  1. 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;
}
  1. 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

  1. Run any recent Netdata (stable 2.10.4 or nightly)
  2. Wait for some alerts to be stored
  3. curl http://localhost:19999/api/v1/alarm_log
  4. 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
  • Issue [Feat]: Let alert history be queryable / log alerts to file #15399 confirms /api/v1/alarm_log is the intended endpoint for alert history

Environment

  • OS: Ubuntu ARM64 (Oracle Cloud Ampere A1)
  • Netdata: v2.10.4 (stable) and v2.10.0-980-nightly
  • Docker: netdata/netdata containers, dbengine mode

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions