stablyai/orca · error
resolved values differ for ${baseRef}:\n serial ${JSON.
Error message
resolved values differ for ${baseRef}:\n serial ${JSON.stringify(serial)}\n concurrent ${JSON.stringify(concurrent)} What it means
Thrown by the branch-compare-head benchmark as a correctness guard: for each baseRef it runs readSerial (the pre-fix serial chain) and readConcurrent (the production concurrent reader readBranchCompareHead) and JSON.stringifies both. A mismatch means the production concurrent path resolves a different compareRef/resolvedBaseRef/headOid/baseOid than the serial reference, i.e. the optimization changed semantics — a real bug, not a benchmark maintenance issue.
Source
Thrown at config/scripts/branch-compare-head-benchmark.mjs:175
console.log('getBranchCompare head-of-chain reads, per call. Lower is better.')
console.log(`iterations=${ITERATIONS} warmup=${WARMUP} rounds=${ROUNDS} (per-arm medians)`)
console.log(
`${pad('base ref', 30)} ${pad('serial', 11)} ${pad('concurrent', 11)} ${pad('speedup', 9)}`
)
// A short remote label is the common case (Orca's base picker emits `origin/main`); the
// already-qualified ref skips the probe entirely, so only the concurrency half applies.
const upstream = await git(['rev-parse', '--abbrev-ref', 'HEAD@{upstream}']).catch(() => null)
const baseRefs = ['origin/main', 'refs/remotes/origin/main', 'main']
if (upstream && !baseRefs.includes(upstream)) {
baseRefs.push(upstream)
}
for (const baseRef of baseRefs) {
const serial = await readSerial(baseRef)
const concurrent = await readConcurrent(baseRef)
if (JSON.stringify(serial) !== JSON.stringify(concurrent)) {
throw new Error(
`resolved values differ for ${baseRef}:\n serial ${JSON.stringify(serial)}\n concurrent ${JSON.stringify(concurrent)}`
)
}
if (!serial.headOid) {
throw new Error(`fixture resolved no HEAD oid for ${baseRef}`)
}
const { serialMs, concurrentMs } = await measure(baseRef)
console.log(
`${pad(baseRef, 30)} ${pad(`${serialMs.toFixed(1)} ms`, 11)} ${pad(`${concurrentMs.toFixed(1)} ms`, 11)} ${pad(`${(serialMs / concurrentMs).toFixed(2)}x`, 9)}`
)
}
console.log(
'\nThe already-qualified refs/... row skips the probe by design, so it only shows the\nconcurrency half. This times the native/WSL head-of-chain reads, not the whole compare;\nthe relay path has separate production-concurrency coverage.'
)
View on GitHub (pinned to 1136503c6a)
Solutions
- Inspect the printed JSON for both arms — the differing field (usually resolvedBaseRef or baseOid) identifies the bug location.
- Diff readBranchCompareHead in src/shared/git-branch-compare-head.ts against the serial reference in the benchmark and reconcile the resolution rule.
- For annotated-tag refs/remotes/* refs, confirm both arms dereference to the commit oid (^{commit}) consistently.
- Add a unit test in the production test suite capturing this baseRef so the divergence cannot recur silently.
Example fix
// before — concurrent arm reuses probe oid for refs/remotes/* (unsafe for annotated tags)
// -> 'resolved values differ for origin/main:\n serial {...}\n concurrent {...}'
// after — only reuse probe oids for refs/heads/* (the optimization's invariant)
// if (candidate.startsWith('refs/heads/')) {
// reusableProbedOidByRef.set(candidate, oid)
// } Defensive patterns
Strategy: validation
Validate before calling
function assertArmsAgree(baseRef, serial, concurrent) {
if (JSON.stringify(serial) !== JSON.stringify(concurrent)) {
throw new Error(`Serial vs concurrent divergence on ${baseRef} — production readBranchCompareHead changed semantics.\n serial ${JSON.stringify(serial)}\n concurrent ${JSON.stringify(concurrent)}`)
}
}
// call after both arms resolve, before timing Prevention
- When editing readBranchCompareHead, run this benchmark before merging — it will catch a semantic regression.
- Keep the benchmark's readSerial as a deliberate reference; do not 'optimize' it to match the concurrent arm.
- Add a unit test in src/shared/git-branch-compare-head.test.ts covering each baseRef shape so divergences surface in CI without the benchmark.
When it happens
Trigger: readBranchCompareHead in src/shared/git-branch-compare-head.ts was edited and now resolves refs differently; the probe-oid reuse optimization (reusableProbedOidByRef) returns the wrong oid for a refs/heads/* ref; the candidate-ordering in resolveBaseRef changed; an annotated-tag handling rule diverged between the two arms.
Common situations: A speed optimization to the head-of-chain reads changed which candidate wins; the serial path was updated but the concurrent path was not (or vice versa); remote-tracking refs that store annotated tags now resolve to a tag oid in one arm but a commit oid in the other.
Related errors
- normalizer mismatch at ${kb} KB
- ${name} must be a positive integer, received ${value}
- no benchmark file exists at both HEAD and HEAD~1 in this che
- Commit or stash changes before running the provenance-bound
- projection mismatch at ${agents} agents
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/75bbc659f7052a54.
Report an issue: GitHub.