can1357/oh-my-pi · error · InvalidIssueRef

expected owner/repo#NN or https://github.com/owner/repo/issu

Error message

expected owner/repo#NN or https://github.com/owner/repo/issues/NN, got {ref!r}

What it means

InvalidIssueRef raised by parse_issue_ref when the input matches neither the `owner/repo#NN` pattern nor a GitHub issue URL. It is the module's validation gate for all manual triage entry points.

Source

Thrown at python/robomp/src/manual_triage.py:56

        super().__init__(f"{delivery_id} is already {state}")


class ManualTriageTimeout(TimeoutError):
    """Raised when a manual CLI waiter stops before terminal state."""

    def __init__(self, delivery_id: str, state: str, timeout_seconds: float) -> None:
        self.delivery_id = delivery_id
        self.state = state
        self.timeout_seconds = timeout_seconds
        super().__init__(f"{delivery_id} did not reach a terminal state within {timeout_seconds:g}s (state={state})")


def parse_issue_ref(ref: str) -> tuple[str, int]:
    """Parse `owner/repo#NN` or a github issue url into `("owner/repo", NN)`."""
    cleaned = ref.strip()
    match = _ISSUE_REF.match(cleaned) or _ISSUE_URL.match(cleaned)
    if match is None:
        raise InvalidIssueRef(f"expected owner/repo#NN or https://github.com/owner/repo/issues/NN, got {ref!r}")
    return f"{match.group('owner')}/{match.group('repo')}", int(match.group("number"))


def manual_delivery_id(repo_full: str, number: int) -> str:
    """Stable delivery id for manually-triggered triage. Re-runs reuse it."""
    return f"manual-{repo_full.replace('/', '__')}-{number}"


async def build_issues_opened_payload(github: GitHubBackend, repo_full: str, number: int) -> dict[str, Any]:
    """Fetch the issue + repo metadata and synthesize an `issues.opened` payload."""
    issue = await github.get_issue(repo_full, number)
    if issue.is_pull_request:
        raise ManualTriageError(f"{repo_full}#{number} is a pull request, not an issue")
    repo = await github.get_repo(repo_full)
    return {
        "action": "opened",
        "issue": {
            "number": issue.number,

View on GitHub (pinned to 9690622007)

Solutions

  1. Use full `owner/repo#123` format or `https://github.com/owner/repo/issues/123`
  2. If input may be a PR link, convert `pull/NN` to `issues/NN` only if the item is actually an issue
  3. Trim and validate the string before passing it in

Example fix

// before
triage("#123")
// after
triage("my-org/my-repo#123")
Defensive patterns

Strategy: validation

Validate before calling

import re
_ISSUE_REF = re.compile(r"^(?P<owner>[\w.-]+)/(?P<repo>[\w.-]+)#(?P<number>\d+)$")
_ISSUE_URL = re.compile(r"^https://github\.com/(?P<owner>[\w.-]+)/(?P<repo>[\w.-]+)/issues/(?P<number>\d+)$")
def valid_ref(ref: str) -> bool:
    c = ref.strip()
    return bool(_ISSUE_REF.match(c) or _ISSUE_URL.match(c))

Try / catch

try:
    owner_repo, number = parse_issue_ref(ref)
except InvalidIssueRef as e:
    return f"bad issue ref: {e}"

Prevention

When it happens

Trigger: api_trigger or triage receiving refs like "123", "repo#12", "https://github.com/owner/repo/pull/12", or whitespace-mangled strings.

Common situations: Users pasting PR URLs instead of issue URLs, bare issue numbers, or repo names without owner prefixes into the triage API/dashboard.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ceaa0a9cd889814a. Report an issue: GitHub.