can1357/oh-my-pi · warning · HTTPException
unknown delivery {delivery_id}
Error message
unknown delivery {delivery_id} What it means
FastAPI raises HTTP 404 with 'unknown delivery {delivery_id}' from POST /api/cancel when no event row with that delivery_id exists in the SQLite events table. The cancel endpoint first validates the delivery_id is a non-empty string (400 otherwise), then looks it up via db.get_event(); a miss means the id is not a real delivery this server ever received.
Source
Thrown at python/robomp/src/server.py:689
request: Request,
payload: dict[str, Any] = Body(...),
x_robomp_token: str | None = Header(None, alias="X-Robomp-Replay-Token"),
) -> JSONResponse:
"""Stop a running event. The omp subprocess is killed; the row lands in
`failed` with `cancelled by operator` as the error.
"""
bag = request.app.state.bag
cfg: Settings = bag["settings"]
_require_trigger_token(cfg, x_robomp_token)
delivery_id = payload.get("delivery_id")
if not isinstance(delivery_id, str) or not delivery_id:
raise HTTPException(400, "cancel requires 'delivery_id'")
db: Database = bag["db"]
event = db.get_event(delivery_id)
if event is None:
raise HTTPException(404, f"unknown delivery {delivery_id}")
if event.state != "running":
raise HTTPException(
409, f"delivery {delivery_id} is {event.state}; only running deliveries can be cancelled"
)
pool: WorkerPool = bag["pool"]
fired = await pool.cancel_event(delivery_id)
log.info(
"manual cancel",
extra={"delivery": delivery_id, "fired": fired, "state": event.state},
)
return JSONResponse(
{"delivery": delivery_id, "fired": fired, "previous_state": event.state},
status_code=202,
)
@app.get("/events")
async def events(request: Request, limit: int = 50) -> dict[str, Any]:View on GitHub (pinned to 9690622007)
Solutions
- List real ids with GET /events and use the delivery_id shown there (or click cancel in the dashboard, which uses ids from that listing).
- Check you are hitting the same robomp instance that received the webhook (correct host/port, same docker compose project).
- Verify the /data volume persists; a recreated container with an anonymous volume loses the events DB.
- Re-run the task with POST /api/trigger (triage mode) instead of cancelling if the delivery never existed on this server.
Example fix
// before
curl -X POST /api/cancel -d '{"delivery_id":"abc-123"}' // 404 unknown delivery abc-123
// after
ID=$(curl -s localhost:8080/events | jq -r '.events[] | select(.state=="running") | .delivery_id' | head -1)
curl -X POST /api/cancel -H 'Content-Type: application/json' -d "{\"delivery_id\":\"$ID\"}" Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch('/events');
const { events } = await res.json();
const known = new Set(events.map(e => e.delivery_id));
if (!known.has(deliveryId)) throw new Error(`unknown delivery ${deliveryId}: check /events`); Type guard
function isDeliveryId(v: unknown): v is string {
return typeof v === 'string' && v.length > 0;
} Try / catch
try {
await api.cancel(deliveryId);
} catch (e) {
if (e instanceof ApiError && e.status === 404) {
console.warn(`delivery ${deliveryId} not found; refresh the event list`);
} else throw e;
} Prevention
- Always source delivery ids from GET /events or the dashboard, never from GitHub webhook logs.
- Drive cancels through the dashboard UI, which lists live ids.
- Keep the /data volume persistent so event rows survive container recreation.
- Check you are targeting the same robomp deployment that received the webhook.
When it happens
Trigger: POST /api/cancel with a delivery_id that was never recorded, a typo'd/copied-wrong id, an id from a different robomp instance (fresh /data volume or different deployment), or an id purged by database reset/retention.
Common situations: Operator copies a delivery id from GitHub's webhook log instead of from /events; the container was recreated with an empty /data volume so the SQLite rows are gone; typo in curl/dashboard invocation; pointing the dashboard at the wrong backend.
Related errors
- AuthBrokerStreamUnsupportedError
- This share no longer exists (gist deleted?).
- Conflict #${id} not found. Conflict ids are registered when
- Bulk directive references unknown conflict id(s) ${unknown.m
- missing/invalid 'slot_uid'
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/33882010b3a6f80f.
Report an issue: GitHub.