{"record":{"id":"1c5433a0ad619873","repo":"can1357/oh-my-pi","slug":"no-retryable-stored-event-for-repo-full-number","errorCode":null,"errorMessage":"no retryable stored event for {repo_full}#{number}","messagePattern":"no retryable stored event for (.+?)#(.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"python/robomp/src/server.py","lineNumber":652,"sourceCode":"            log.info(\"manual triage\", extra={\"delivery\": delivery, \"issue\": f\"{repo_full}#{number}\"})\n            return JSONResponse(\n                {\"delivery\": delivery, \"state\": \"queued\", \"mode\": \"triage\"},\n                status_code=202,\n            )\n\n        # mode == \"retry\"\n        if isinstance(delivery_id, str) and delivery_id:\n            target = delivery_id\n        elif isinstance(issue_ref, str) and issue_ref:\n            try:\n                repo_full, number = parse_issue_ref(issue_ref)\n            except InvalidIssueRef as exc:\n                raise HTTPException(400, str(exc)) from exc\n            if not cfg.allows(repo_full):\n                raise HTTPException(403, f\"{repo_full} not in ROBOMP_REPO_ALLOWLIST\")\n            row = db.latest_event_for_issue(make_issue_key(repo_full, number))\n            if row is None:\n                raise HTTPException(404, f\"no retryable stored event for {repo_full}#{number}\")\n            target = row.delivery_id\n        else:\n            raise HTTPException(400, \"retry requires 'delivery_id' or 'issue'\")\n\n        event = db.get_event(target)\n        if event is None:\n            raise HTTPException(404, f\"unknown delivery {target}\")\n        if not db.requeue_event(target, from_states=INACTIVE_EVENT_STATES):\n            raise HTTPException(409, f\"delivery {target} is {event.state}; only inactive events can be retried\")\n        pool.wake()\n        log.info(\"manual retry\", extra={\"delivery\": target})\n        return JSONResponse(\n            {\"delivery\": target, \"state\": \"queued\", \"mode\": \"retry\"},\n            status_code=202,\n        )\n\n    @app.post(\"/api/cancel\")\n    async def api_cancel(","sourceCodeStart":634,"sourceCodeEnd":670,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/server.py#L634-L670","documentation":"The retry endpoint accepted a valid, allowlisted issue ref but the database has no stored event to retry, returning HTTP 404 'no retryable stored event for owner/repo#N'. Retries work by re-processing the most recent stored webhook delivery for that issue (db.latest_event_for_issue); if the database has never recorded a delivery for it, there is nothing to replay.","triggerScenarios":"POSTing to the retry endpoint with `issue: 'owner/repo#N'` where `db.latest_event_for_issue(make_issue_key(repo_full, number))` returns None — no webhook delivery for that issue was ever persisted (or it was purged/rotated out of the store).","commonSituations":"Trying to retry an issue that was created manually and never arrived via webhook; the database was reset/migrated and old events are gone; event retention pruning removed the delivery; typo in the issue number pointing at an issue the bot never saw.","solutions":["Confirm the issue previously arrived via webhook (check server logs or the events listing) before retrying","Use `delivery_id` from the original webhook instead of `issue` if you have it","Trigger a fresh triage via the trigger endpoint instead of a retry, since no stored event exists","Check database retention/cleanup settings if events are disappearing sooner than expected"],"exampleFix":"// before: retry by issue when nothing is stored\nPOST /retry { \"issue\": \"acme/widgets#42\" }\n// after: replay the known delivery\nPOST /retry { \"delivery_id\": \"uuid-from-webhook-header\" }","handlingStrategy":"validation","validationCode":"// Confirm a stored event exists for the issue before retrying by ref\nconst evt = await api.getLatestEventForIssue('acme/widgets#42');\nif (!evt) {\n  throw new Error('no stored delivery for this issue; use trigger (fresh triage) instead of retry');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.retry({ issue: issueRef });\n} catch (err) {\n  if (err.status === 404 && /no retryable stored event/.test(err.message)) {\n    logger.warn('nothing to replay; falling back to fresh trigger', { issueRef });\n    await api.trigger({ issue: issueRef });\n  } else throw err;\n}","preventionTips":["Prefer delivery_id (from the original webhook) over issue refs when available","Only retry issues that actually arrived via webhook to this instance","Check database retention settings if events vanish unexpectedly","Fall back to the trigger endpoint when retry reports no stored event"],"tags":["http-404","not-found","retry","database","missing-data"],"backgroundTag":"event-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}