stablyai/orca · error

${name} canonical placement did not update to the PR content

Error message

${name} canonical placement did not update to the PR content

What it means

assertCurrentCanonical() computes a package digest of the installed canonical placement (~/.agents/skills/<name>) and compares it to currentSkill(name).packageDigest from the manifest. It throws when they differ — meaning the 'skills update <name> --global' command did not bring the canonical install up to the manifest's declared digest.

Source

Thrown at config/scripts/verify-skill-update-roundtrip.mjs:133

    await writeFile(
      executable,
      process.platform === 'win32' ? '@exit /b 0\r\n' : '#!/bin/sh\nexit 0\n'
    )
    if (process.platform !== 'win32') {
      await chmod(executable, 0o755)
    }
  }
}

async function packageDigestAt(pathValue) {
  return packageDigest(await collectPackageFiles(pathValue))
}

async function assertCurrentCanonical(name) {
  const expected = currentSkill(name).packageDigest
  const canonical = path.join(home, '.agents', 'skills', name)
  if ((await packageDigestAt(canonical)) !== expected) {
    throw new Error(`${name} canonical placement did not update to the PR content`)
  }
}

function execSkills(args) {
  const executable = process.platform === 'win32' ? (process.env.ComSpec ?? 'cmd.exe') : 'npx'
  const cliArgs = ['--yes', `skills@${cliVersion}`, ...args]
  execFileSync(
    executable,
    process.platform === 'win32' ? ['/d', '/s', '/c', 'npx.cmd', ...cliArgs] : cliArgs,
    {
      cwd: process.cwd(),
      env: {
        ...process.env,
        HOME: home,
        USERPROFILE: home,
        CODEX_HOME: path.join(home, '.codex'),
        CLAUDE_CONFIG_DIR: path.join(home, '.claude'),
        XDG_STATE_HOME: stateHome,

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Confirm current-manifest.json packageDigest matches the published package the CLI downloads.
  2. Run the update manually and inspect ~/.agents/skills/<name> to see what was actually written.
  3. Ensure autocrlf is set as declared (--autocrlf=false avoids CRLF rewrites that change the digest).
  4. Verify HOME / stateHome in the sandbox point where the script expects (the script sets these up; external overrides break it).
  5. Re-run the manifest digest-generation step to keep it in sync with the package.
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check the manifest digest against a freshly computed one before running updates:
import { createHash } from 'node:crypto'
async function recomputeDigest(skillDir) { /* same algorithm the manifest generator uses */ }
// If recomputeDigest(canonicalDir) !== manifest.packageDigest, the manifest is stale —
// regenerate it rather than letting the round-trip fail.

Prevention

When it happens

Trigger: The update command failed silently or partially; the manifest digest is stale relative to what the published package actually contains; the update wrote to a different canonical path; file-mode or line-ending normalization makes the recomputed digest differ.

Common situations: Published skill package and manifest digest out of sync; autocrlf rewriting line endings so the on-disk files hash differently than the recorded digest; update command has a bug that skips the canonical placement; HOME/stateHome env misdirection causing install into the wrong directory.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/5f8ee443e5719966. Report an issue: GitHub.