{"record":{"id":"7acd6d8600684bb6","repo":"can1357/oh-my-pi","slug":"invalid-issue-url-unexpected-variant-parsed","errorCode":null,"errorMessage":"Invalid issue:// URL: unexpected variant '${parsed.kind}'","messagePattern":"Invalid issue:// URL: unexpected variant '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/internal-urls/issue-pr-protocol.ts","lineNumber":532,"sourceCode":"\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,\n\t\t\t\tscheme: \"issue\",\n\t\t\t\tparsed,\n\t\t\t\trendered: lookup.rendered,\n\t\t\t\tstatus: lookup.status,\n\t\t\t\tfetchedAt: lookup.fetchedAt,\n\t\t\t});","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/internal-urls/issue-pr-protocol.ts#L514-L550","documentation":"Defensive exhaustiveness guard in IssueProtocolHandler.resolve (packages/coding-agent/src/internal-urls/issue-pr-protocol.ts:532). parseUrl already rejects issue://.../diff URLs and the union of parsed kinds is expected to be 'list' | 'single'; if any other variant appears, TypeScript's narrowing has failed (union grew without the handler being updated). This throw is a belt-and-suspenders catch, not a user-facing validation.","triggerScenarios":"Only reachable if ParsedUrl union for the 'issue' scheme gains a new kind (e.g. a future issue-diff variant) and IssueProtocolHandler.resolve is not updated, or if parseUrl's narrowing/discrimination is broken by a refactor.","commonSituations":"Maintainer adds a new parsed-kind to the shared parseUrl union and only updates PrProtocolHandler; type-level exhaustiveness wasn't enforced so the new kind silently reaches this guard at runtime.","solutions":["Update IssueProtocolHandler.resolve to handle the new parsed.kind variant — the error names the unexpected variant, so read it from the message.","Check parseUrl in issue-pr-protocol.ts to see which variants it can return for the 'issue' scheme and confirm the union.","Add an exhaustive switch (or a `satisfies never` check) so TypeScript flags a missing variant at compile time instead of this runtime throw.","If you hit this as a user, it is a library bug — report it with the URL that triggered it."],"exampleFix":"// before\nif (parsed.kind !== \"single\") {\n  throw new Error(`Invalid issue:// URL: unexpected variant '${parsed.kind}'`);\n}\n// after\nswitch (parsed.kind) {\n  case \"single\": break;\n  case \"issue-diff\": /* handle new variant */ break;\n  default: {\n    const _exhaustive: never = parsed;\n    throw new Error(`Invalid issue:// URL: unexpected variant '${String(_exhaustive)}'`);\n  }\n}","handlingStrategy":"type-guard","validationCode":"null","typeGuard":"function isKnownIssueKind(parsed: ParsedUrl): parsed is Extract<ParsedUrl, { kind: \"list\" | \"single\" }> {\n  return parsed.kind === \"list\" || parsed.kind === \"single\";\n}","tryCatchPattern":"try {\n  return await issueHandler.resolve(url, ctx);\n} catch (err) {\n  if (/Invalid issue:\\/\\/ URL: unexpected variant/.test(String(err.message))) {\n    throw new Error(`Library bug in issue-pr-protocol parseUrl/handler union: ${err instanceof Error ? err.message : err}`);\n  }\n  throw err;\n}","preventionTips":["When extending the parsed-kind union, update both IssueProtocolHandler and PrProtocolHandler in the same change.","Use an exhaustive switch with a `never` assignment so missing variants fail at compile time.","Add a unit test per parsed kind exercising each handler.","Treat occurrences at runtime as library bugs and report them with the URL."],"tags":["internal-invariant","exhaustiveness","typescript","protocol-handler"],"backgroundTag":"unhandled-variant","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}