stablyai/orca · error
malformed stack
Error message
malformed stack
What it means
Thrown by getRestPRByNumber when requireUsableStackMetadata is set, restData.stack is present and non-null, but isUsableRestStackMetadata rejects it OR mapRestPullRequest did not produce a stack. GitHub omits the stack field for ordinary PRs (which is fine — that path is skipped); only a non-null but unusable value triggers this. It guards against partial or malformed stack metadata that would render an inconsistent PR stack view.
Source
Thrown at src/main/github/client.ts:3008
): Promise<PullRequestLookupData> {
const { stdout } = await ghExecFileAsync(
['api', `repos/${ownerRepo.owner}/${ownerRepo.repo}/pulls/${number}`],
{ ...ghOptions, ...githubHostExecOptions(ownerRepo) }
)
const parsed = JSON.parse(stdout) as unknown
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error('invalid response shape')
}
const restData = parsed as RestPullRequest
const mapped = mapRestPullRequest(restData)
if (
options.requireUsableStackMetadata &&
restData.stack !== undefined &&
restData.stack !== null
) {
// Why: GitHub omits stack for ordinary PRs; only unusable non-null metadata is unsafe.
if (!isUsableRestStackMetadata(restData.stack) || !mapped.stack) {
throw new Error('malformed stack')
}
if (!isGitObjectId(restData.head?.sha)) {
throw new Error('missing head SHA')
}
}
return mapped
}
function prunePRStackSummaryCache(now = Date.now()): void {
for (const [key, cached] of prStackSummaryCache) {
if (cached.expiresAt <= now) {
prStackSummaryCache.delete(key)
}
}
while (prStackSummaryCache.size > PR_STACK_SUMMARY_CACHE_MAX_ENTRIES) {
const oldestKey = prStackSummaryCache.keys().next().value
if (oldestKey === undefined) {
returnView on GitHub (pinned to 1136503c6a)
Solutions
- Inspect the raw `stack` field from `gh api repos/<owner>/<repo>/pulls/<n>` and compare against isUsableRestStackMetadata's requirements.
- If the shape is genuinely new, file an issue — the mapper may need to recognize the new format.
- As a workaround, calls without requireUsableStackMetadata will tolerate the field; use that path for display-only contexts.
Defensive patterns
Strategy: validation
Validate before calling
import { isUsableRestStackMetadata } from './stack-metadata'
function stackIsUsable(stack: unknown): boolean {
return stack == null || isUsableRestStackMetadata(stack)
} Type guard
function isUsableRestStackMetadataShape(stack: unknown): boolean {
return typeof stack === 'object' && stack !== null &&
Array.isArray((stack as any).entries) && (stack as any).entries.length > 0
} Try / catch
try {
const pr = await getRestPRByNumber(ownerRepo, number, ghOptions, { requireUsableStackMetadata: true })
} catch (err) {
if ((err as Error).message === 'malformed stack') {
// fall back to non-stack-aware lookup for display only
return getRestPRByNumber(ownerRepo, number, ghOptions)
}
throw err
} Prevention
- For display-only contexts, call without requireUsableStackMetadata to tolerate partial stack data.
- Track GitHub stack-format changes and update isUsableRestStackMetadata promptly.
- Log the raw stack field when this fires so new shapes are caught early.
When it happens
Trigger: GitHub returns a stack object missing required child entries; the stack payload references PR numbers that didn't map; a beta stack feature returned a shape the mapper doesn't yet understand; the gh CLI or GitHub Enterprise served a partially-serialized stack.
Common situations: GitHub rolls out a stack-format change; a stacked-PR tool (Graphite, gh-stack) writes metadata in a non-standard shape; Enterprise Server lags behind on stack API fields.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- missing head SHA
- repo is required
- token is required
- GitHub request failed ${res.status} ${res.statusText}: ${bod
- GitHub releases response for ${repo} was not an array
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/aca200b9b726b09b.
Report an issue: GitHub.