{"record":{"id":"7c6e6993fd12fe4a","repo":"can1357/oh-my-pi","slug":"issue-listing-failed-message","errorCode":null,"errorMessage":"issue:// listing failed: ${message}","messagePattern":"issue:// listing failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/internal-urls/issue-pr-protocol.ts","lineNumber":526,"sourceCode":"\n/**\n * Handler for `issue://` URLs.\n */\nexport class IssueProtocolHandler implements ProtocolHandler {\n\treadonly scheme = \"issue\";\n\treadonly immutable = true;\n\n\tasync resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource> {\n\t\tif (context?.signal?.aborted) {\n\t\t\tthrow new Error(\"aborted\");\n\t\t}\n\t\tconst parsed = parseUrl(url, \"issue\");\n\t\tif (parsed.kind === \"list\") {\n\t\t\ttry {\n\t\t\t\treturn await fetchAndRenderList(\"issue\", parsed, url, context);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tthrow new Error(`issue:// listing failed: ${message}`);\n\t\t\t}\n\t\t}\n\t\t// parseUrl already rejects `issue://.../diff`; this guard is a belt-and-\n\t\t// suspenders catch in case the union grows.\n\t\tif (parsed.kind !== \"single\") {\n\t\t\tthrow new Error(`Invalid issue:// URL: unexpected variant '${parsed.kind}'`);\n\t\t}\n\t\ttry {\n\t\t\tconst lookup = await getOrFetchIssue({\n\t\t\t\tcwd: resolveCwd(context),\n\t\t\t\trepo: parsed.repo,\n\t\t\t\tissue: String(parsed.number),\n\t\t\t\tincludeComments: parsed.comments,\n\t\t\t\tsignal: context?.signal,\n\t\t\t\tsettings: settingsFromContext(context),\n\t\t\t});\n\t\t\treturn buildSingleResource({\n\t\t\t\turl,","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/internal-urls/issue-pr-protocol.ts#L508-L544","documentation":"Wrapper error thrown by IssueProtocolHandler.resolve (packages/coding-agent/src/internal-urls/issue-pr-protocol.ts:526) when fetchAndRenderList — the listing path for issue://owner/repo (optionally ?comments=) — fails. The original error's message is preserved via `issue:// listing failed: ${message}`. The scheme prefix distinguishes it from the equivalent pr:// listing wrapper.","triggerScenarios":"Resolving an issue:// listing URL when the underlying list fetch fails: gh CLI missing or unauthenticated, network failure reaching GitHub, invalid repo slug (owner/repo typo or private repo without access), or git remote unresolvable for a repo-less issue://<n> URL.","commonSituations":"No `gh` installed or not logged in; rate-limited by GitHub API; mistyped owner/repo in the URL; offline; repo-less short form used outside a git repository with no GitHub remote.","solutions":["Read the inner message after the prefix — it carries the actual cause (auth, network, repo-not-found) — and fix that.","Run `gh auth status` and `gh auth login` if the inner message indicates authentication failure.","Verify the repo slug: use the explicit issue://owner/repo form instead of the bare issue://<n> form.","Check network connectivity / GitHub API rate limits (gh api rate_limit) and retry after the limit resets.","Ensure the session cwd is inside the intended git repository when relying on default-repo resolution."],"exampleFix":"// before\nconst res = await handler.resolve(parse(\"issue://acme/widgets\"));\n// after\ntry {\n  const res = await handler.resolve(parse(\"issue://acme/widgets\"));\n} catch (err) {\n  if (!String(err.message).startsWith(\"issue:// listing failed:\")) throw err;\n  const cause = String(err.message).replace(\"issue:// listing failed: \", \"\");\n  console.error(`Cannot list issues: ${cause}`);\n}","handlingStrategy":"try-catch","validationCode":"// Verify prerequisites before resolving:\nconst gh = $which(\"gh\");\nif (!gh) throw new Error(\"gh CLI not installed\");\nconst auth = await $`gh auth status`.quiet().nothrow();\nif (auth.exitCode !== 0) throw new Error(\"gh not authenticated\");\nif (!/^issue:\\/\\/[^/]+\\/[^/]+/.test(url.href)) throw new Error(\"use issue://owner/repo form\");","typeGuard":"function isIssueListFailure(err: unknown): err is Error {\n  return err instanceof Error && err.message.startsWith(\"issue:// listing failed: \");\n}","tryCatchPattern":"try {\n  return await issueHandler.resolve(url, ctx);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"issue:// listing failed: \")) {\n    const cause = err.message.slice(\"issue:// listing failed: \".length);\n    logger.warn(\"issue listing failed\", { cause });\n    return null; // degrade gracefully\n  }\n  throw err;\n}","preventionTips":["Install and authenticate the gh CLI (`gh auth login`) before relying on issue:// URLs.","Prefer explicit issue://owner/repo forms over repo-less short forms.","Monitor GitHub rate limits in long-running sessions and back off.","Validate repo slugs (owner/repo) before constructing URLs."],"tags":["github","network","authentication","error-wrapping","protocol-handler"],"backgroundTag":"github-fetch-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}