block/buzz · error

count, gate off

Error message

count, gate off

What it means

This is `.expect("count, gate off")` on `db.count_events_routed("test_count", &q)` in `count_events_routed_is_bounded_only`. It panics if the count query fails while the replica-read budget is unset (routing gate disabled, so the count runs on the writer). The expect converts any sqlx/database error into a panic labeled with the routing arm being proven.

Source

Thrown at crates/buzz-db/src/runtime/tests.rs:1627

    let mut db = Db::from_pools(writer.clone(), replica.clone());
    db.fence().force_open_for_tests(chrono::Utc::now());
    let cid = CommunityId::from_uuid(community);

    // Covered-eligible shape on purpose: pinned + until. A count must
    // ignore that eligibility.
    let q = {
        let mut q = EventQuery::for_community(cid);
        q.channel_id = Some(channel);
        q.until = chrono::DateTime::from_timestamp((base + 60) as i64, 0);
        q
    };

    // Budget unset ⇒ bounded arm disabled ⇒ writer.
    let n = db
        .count_events_routed("test_count", &q)
        .await
        .expect("count, gate off");
    assert_eq!(n, 2, "budget unset must count on the writer");

    // Budget set + fresh entry ⇒ bounded arm ⇒ replica.
    db.set_replica_read_max_age_for_tests(Some(std::time::Duration::from_secs(5)));
    let n = db
        .count_events_routed("test_count", &q)
        .await
        .expect("count, gate on");
    assert_eq!(n, 1, "budget set must count on the replica (bounded)");

    // Entry older than the budget ⇒ bounded fails ⇒ writer. Covered
    // would still hold here (upper <= wall) — proving count never
    // consults it.
    db.fence().close();
    db.fence().force_open_for_tests_at(
        chrono::Utc::now(),
        std::time::Instant::now() - std::time::Duration::from_secs(10),
    );

View on GitHub (pinned to dad5a33865)

Solutions

  1. Ensure Postgres is running and the writer scratch DB was created and migrated.
  2. Confirm `seed_community_channel` ran on the writer before counting.
  3. Inspect the underlying sqlx error by replacing expect with a panic that prints `{e}`.
  4. Re-run the test alone (`cargo test -p buzz-db count_events_routed -- --ignored`) to rule out cross-test interference on shared scratch names.
  5. Check the EventQuery (`for_community` + channel_id + until) matches seeded data shape.

Example fix

// before
let n = db.count_events_routed("test_count", &q).await.expect("count, gate off");
// after
let n = db.count_events_routed("test_count", &q).await
    .unwrap_or_else(|e| panic!("count (gate off / writer) failed: {e}"));
Defensive patterns

Strategy: validation

Validate before calling

// Verify the writer is ready and seeded before counting
sqlx::query("SELECT 1 FROM communities LIMIT 1").execute(&writer).await
    .expect("writer schema missing — run migrations");

Type guard

fn writer_reachable(pool: &sqlx::PgPool) -> bool { pool.size() > 0 }

Try / catch

let n = match db.count_events_routed("test_count", &q).await {
    Ok(n) => n,
    Err(e) => panic!("writer count failed: {e}"),
};

Prevention

When it happens

Trigger: Calling `count_events_routed` on the writer pool with `set_replica_read_max_age_for_tests` never invoked, when the writer scratch DB is unreachable, missing the events schema, or the seeded rows/community/channel rows are absent causing a constraint or SQL error.

Common situations: Scratch DBs created without migrations applied; writer pool connection dropped mid-test; test run without Postgres; divergent seed helpers failing silently earlier leaving the query shape invalid.

Related errors


AI-assisted analysis of block/buzz@dad5a33865 (2026-08-30). Data as JSON: /api/errors/50c04cd08054faf8. Report an issue: GitHub.