block/buzz · error · IngestError::Rejected

db error looking up target: {e}

Error message

db error looking up target: {e}

What it means

Thrown when the Postgres lookup of the delete target (get_event_by_id) itself errors — an infrastructure failure, not a validation or permission problem. The underlying database error is interpolated into the message ({e}), so inspect it to identify connectivity, timeout, or constraint issues. The delete event is rejected without side effects and is safe to retry.

Source

Thrown at crates/buzz-relay/src/handlers/side_effects.rs:656

            let target_id = event
                .tags
                .iter()
                .find_map(|tag| {
                    if tag.kind().to_string() == "e" {
                        tag.content().and_then(|v| hex::decode(v).ok())
                    } else {
                        None
                    }
                })
                .ok_or_else(|| anyhow::anyhow!("missing e tag for target event"))?;

            // Verify the target event exists and belongs to the h-tag channel
            // BEFORE storage. Fail closed: missing target → reject.
            let target_event = state
                .db
                .get_event_by_id(tenant.community(), &target_id)
                .await
                .map_err(|e| anyhow::anyhow!("db error looking up target: {e}"))?
                .ok_or_else(|| anyhow::anyhow!("target event not found"))?;

            match target_event.channel_id {
                Some(target_ch) if target_ch != channel_id => {
                    return Err(anyhow::anyhow!(
                        "target event belongs to a different channel"
                    ));
                }
                None => {
                    return Err(anyhow::anyhow!("target event has no channel"));
                }
                _ => {} // Same channel — OK
            }

            // Check if actor is the event author.
            // For relay-signed REST messages, the real author is in the p tag.
            let author =
                effective_message_author(&target_event.event, &state.relay_keypair.public_key());

View on GitHub (pinned to f956e6fe06)

Solutions

  1. Check the relay logs and the embedded {e} cause — 'connection refused' means Postgres is down, 'timeout' means load/locking.
  2. Start/verify the database (docker compose up -d postgres or just setup) and retry the publish — the operation is idempotent-safe.
  3. For pool exhaustion, reduce concurrent delete publishes or batch them with backoff.
  4. If it persists, check Postgres health (connections, locks, disk) and relay DB config in .env.
Defensive patterns

Strategy: retry

Validate before calling

// Cheap pre-flight: confirm the relay's DB-backed surface is healthy before a delete storm
const health = await fetch(`${relayHttp}/health`);
if (!health.ok) throw new Error("Relay unhealthy — defer deletes and retry later");

Try / catch

async function deleteWithRetry(channelId: string, eventId: string, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await sdk.deleteEvent(channelId, eventId);
    } catch (e) {
      const msg = String(e);
      if (msg.includes("db error looking up target") && i < attempts - 1) {
        await sleep(2 ** i * 500); // exponential backoff — infra error, safe to retry
        continue;
      }
      throw e;
    }
  }
}

Prevention

When it happens

Trigger: Publishing kind:9005 while the relay's Postgres is unreachable, under load (statement timeout), restarting, or when the connection pool is exhausted. Any error from the DB layer during the target lookup maps to this message.

Common situations: Local dev without Postgres running (just relay up, forgot just setup/docker); connection pool saturation under burst delete storms; transient network blips between relay and RDS/Postgres; migrations running concurrently locking the events table.

Related errors


AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16). Data as JSON: /api/errors/4744f654bee93c79. Report an issue: GitHub.