{"record":{"id":"6f02f1077eb1e9af","repo":"can1357/oh-my-pi","slug":"release-state-missing-for-release-key","errorCode":null,"errorMessage":"release state missing for {release_key}","messagePattern":"release state missing for (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/robomp/src/worker.py","lineNumber":812,"sourceCode":"    *,\n    task_kind: str,\n    inputs: TaskInputs,\n    comment: CommentInfo | None = None,\n    pr_number: int | None = None,\n    review_payload: dict[str, Any] | None = None,\n    pr: PullRequestInfo | None = None,\n    directive: DirectiveInfo | None = None,\n    thread: tuple[ThreadMessage, ...] = (),\n) -> str | None:\n    \"\"\"Async wrapper that runs the synchronous RPC driver on a worker thread.\"\"\"\n    review_mode = task_kind == \"review_pr\" or inputs.workspace.branch.startswith(\"review/pr-\")\n    loop = asyncio.get_running_loop()\n    release_binding: ReleaseToolContext | None = None\n    if inputs.release is not None:\n        release_key = f\"{inputs.repo.full_name}#{inputs.release.tag}\"\n        release_row = inputs.db.get_release(release_key)\n        if release_row is None:\n            raise RuntimeError(f\"release state missing for {release_key}\")\n        release_binding = ReleaseToolContext(\n            repo=inputs.repo.full_name,\n            tag=inputs.release.tag,\n            version=inputs.release.version,\n            key=release_key,\n            expected_sha=release_row.current_sha,\n            default_branch=inputs.release.default_branch,\n        )\n    bindings = ToolBindings(\n        db=inputs.db,\n        github=inputs.github,\n        git_transport=inputs.git_transport,\n        repo=inputs.repo,\n        issue=inputs.issue,\n        workspace=inputs.workspace,\n        loop=loop,\n        settings=inputs.settings,\n        author_name=inputs.settings.resolved_author_name,","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/worker.py#L794-L830","documentation":"run_task raises RuntimeError('release state missing for {release_key}') when inputs.release is set (a release-CI/repair task) but db.get_release() finds no row for the key '{repo_full_name}#{tag}'. The release lifecycle rows (awaiting_ci/fixing/green/failed/superseded) in the releases table are the source of truth; without one the worker cannot build the ReleaseToolContext (expected_sha etc.) needed by release host tools.","triggerScenarios":"handle_release_ci dispatches a task for a workflow_run whose release row was never created (webhook for the tag push missed or processed out of order), the row was deleted/rotated, the DB volume was reset, or the tag/key format changed between versions.","commonSituations":"Release rows superseded/removed while a CI verdict was still in flight; testing against an empty sqlite file; replaying an old release delivery after the releases table was cleared; mismatch between the tag in the workflow_run payload and the tag recorded at push time (e.g. annotated vs lightweight tag strings).","solutions":["Check the releases table (GET /releases or sqlite /data/robomp.sqlite 'select * from releases') for the '{repo}#{tag}' key.","Re-trigger the release flow so the row is created: push/re-tag or re-run the release workflow so the webhook records the release before CI handling.","Verify the webhook that creates the release row was received (check server logs / events for the push event); fix webhook connectivity if it was dropped.","If testing, seed the release row via the normal flow rather than calling run_task with a bare inputs.release.","Ensure the tag string matches exactly (including 'v' prefix) between the workflow payload and the recorded release."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"key = f\"{repo.full_name}#{release.tag}\"\nrow = db.get_release(key)\nif row is None:\n    raise RuntimeError(f\"release state missing for {key}; re-run the release flow to create it\")","typeGuard":null,"tryCatchPattern":"try:\n    result = await run_task(task_kind='handle_release_ci', inputs=inputs)\nexcept RuntimeError as e:\n    if 'release state missing' in str(e):\n        log.error('release row absent; re-trigger the release push/workflow to recreate it')\n    else:\n        raise","preventionTips":["Ensure the release row is created by the tag-push webhook before any CI verdict task runs.","Check webhook delivery logs; a missed push event leaves releases untracked.","Do not clear/rotate the releases table while release CI tasks are in flight.","Keep the exact tag string (including 'v' prefix) consistent between push, workflow payload, and DB key.","Seed release rows through the normal flow rather than constructing TaskInputs by hand in tests."],"tags":["release","state-missing","worker","data-integrity"],"backgroundTag":"missing-state-row","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}