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
- Check the relay logs and the embedded {e} cause — 'connection refused' means Postgres is down, 'timeout' means load/locking.
- Start/verify the database (docker compose up -d postgres or just setup) and retry the publish — the operation is idempotent-safe.
- For pool exhaustion, reduce concurrent delete publishes or batch them with backoff.
- 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
- Keep the delete path idempotent so blind retries after DB errors are safe.
- Watch relay logs for the embedded Postgres cause to distinguish outage vs timeout vs pool exhaustion.
- In local dev, always run Postgres (just setup / docker compose) before exercising deletes.
- Rate-limit bulk deletes to avoid saturating the relay's DB pool.
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
- invalid action_id tag
- missing e tag for target event
- target event belongs to a different channel
- target event has no channel
- must be event author or channel owner/admin
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/4744f654bee93c79.
Report an issue: GitHub.