can1357/oh-my-pi · error
pr:// resolution failed: ${message}
Error message
pr:// resolution failed: ${message} What it means
Top-level wrapper error for the single-PR path of PrProtocolHandler.resolve (packages/coding-agent/src/internal-urls/issue-pr-protocol.ts:618). When getOrFetchPr fails for a pr://owner/repo/<n> (or pr://<n> after successful repo resolution) URL, the cause's message is preserved after the `pr:// resolution failed: ` prefix. It is the pr:// counterpart of the issue:// resolution wrapper.
Source
Thrown at packages/coding-agent/src/internal-urls/issue-pr-protocol.ts:618
cwd,
repo,
number: parsed.number,
includeComments: parsed.comments,
signal: context?.signal,
settings: settingsFromContext(context),
});
return buildSingleResource({
url,
scheme: "pr",
parsed,
rendered: lookup.rendered,
status: lookup.status,
fetchedAt: lookup.fetchedAt,
repo,
});
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
throw new Error(`pr:// resolution failed: ${message}`);
}
}
}
View on GitHub (pinned to 9690622007)
Solutions
- Read the inner message after `pr:// resolution failed: ` for the concrete cause (404, auth, network).
- Verify the PR: `gh pr view <n> -R owner/repo` reproduces the fetch independently.
- Run `gh auth login` if the cause indicates authentication/permission failure.
- Use the explicit pr://owner/repo/<n> form to rule out default-repo detection issues (which throw 1538 instead).
- For transient network/rate-limit causes, retry with backoff; cached immutable content may still resolve.
Example fix
// before
const res = await prHandler.resolve(parse("pr://acme/widgets/99"));
// after
try {
const res = await prHandler.resolve(parse("pr://acme/widgets/99"));
} catch (err) {
const cause = String(err.message).replace("pr:// resolution failed: ", "");
if (/rate limit/i.test(cause)) await Bun.sleep(60_000);
else throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
const check = await $`gh pr view ${n} -R ${owner}/${repo} --json number`.quiet().nothrow();
if (check.exitCode !== 0) throw new Error(`PR ${n} not accessible in ${owner}/${repo}`); Type guard
function isPrResolutionFailure(err: unknown): err is Error {
return err instanceof Error && err.message.startsWith("pr:// resolution failed: ");
} Try / catch
try {
return await prHandler.resolve(url, ctx);
} catch (err) {
if (err instanceof Error && err.message.startsWith("pr:// resolution failed: ")) {
const cause = err.message.slice("pr:// resolution failed: ".length);
if (/not found|404/i.test(cause)) return null; // permanently missing
if (/rate limit|timeout|network/i.test(cause)) return retryWithBackoff(() => prHandler.resolve(url, ctx));
throw err;
}
throw err;
} Prevention
- Authenticate gh (`gh auth login`) and confirm repo access before resolving pr:// URLs.
- Use fully-qualified pr://owner/repo/<n> URLs.
- Classify the inner cause to decide retry (network/rate limit) vs permanent failure (404).
- Validate the PR number is a positive integer before building the URL.
- Refresh stale caches after PRs are force-pushed or the repo migrates.
When it happens
Trigger: Resolving a single pr:// URL when the fetch/render of that PR fails: nonexistent PR number, private repo without gh auth, network error, GitHub rate limit, or stale cache whose live refresh 404s.
Common situations: Typo'd PR number or repo slug; PR merged/deleted and not in cache; gh logged out; offline; API secondary rate limiting; private repo not accessible with current credentials.
Related errors
- issue:// listing failed: ${message}
- issue:// resolution failed: ${message}
- pr:// listing failed: ${message}
- pr:// diff resolution failed: ${message}
- assume-role
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5ed882ccbe4b4eb5.
Report an issue: GitHub.