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
- Use full `owner/repo#123` format or `https://github.com/owner/repo/issues/123`
- If input may be a PR link, convert `pull/NN` to `issues/NN` only if the item is actually an issue
- 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
- Always include owner/repo, never a bare #NN
- Convert /pull/NN URLs or reject them before calling
- strip() user input before parsing
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
- Unrecognized source format. Did you mean './${source}' (loca
- Unknown changelog category: ${raw}
- No JSON payload found in response
- Line numbers in @@ header must be >= 1
- Line hint must be >= 1
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ceaa0a9cd889814a.
Report an issue: GitHub.