{"record":{"id":"1ef2106c7c9fdb1c","repo":"nocobase/nocobase","slug":"couldn-t-locate-the-saved-stash-for-source-publish","errorCode":null,"errorMessage":"Couldn't locate the saved stash for source publish: ${params.stash.commit}","messagePattern":"Couldn't locate the saved stash for source publish: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/cli/src/lib/source-publish.ts","lineNumber":209,"sourceCode":"  };\n}\n\nasync function resolveSourcePublishStashReference(params: {\n  cwd: string;\n  stash: SourcePublishStash;\n}): Promise<string> {\n  const output = trimValue(await commandOutput('git', ['stash', 'list', '--format=%gd%x00%H'], {\n    cwd: params.cwd,\n    errorName: 'git stash list',\n  }));\n  for (const line of output.split('\\n')) {\n    const [reference, commit] = line.split('\\x00');\n    if (trimValue(commit) === params.stash.commit) {\n      return trimValue(reference);\n    }\n  }\n\n  throw new Error(`Couldn't locate the saved stash for source publish: ${params.stash.commit}`);\n}\n\nfunction buildSourcePublishRecoveryError(params: {\n  originalError: unknown;\n  cleanupError: unknown;\n  stash?: SourcePublishStash;\n  temporaryBranch: string;\n  projectRoot: string;\n}): Error {\n  const originalMessage = params.originalError instanceof Error\n    ? params.originalError.message\n    : String(params.originalError);\n  const cleanupMessage = params.cleanupError instanceof Error\n    ? params.cleanupError.message\n    : String(params.cleanupError);\n  const recoveryHints = [\n    `Project root: ${params.projectRoot}`,\n    `Temporary branch: ${params.temporaryBranch}`,","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/core/cli/src/lib/source-publish.ts#L191-L227","documentation":"resolveSourcePublishStashReference() scans `git stash list --format=%gd%x00%H` to translate the recorded stash commit SHA into a stash reference (e.g. stash@{0}) so it can be applied/popped. If no stash entry's commit hash matches the SHA captured when the stash was created, the CLI throws this error, because it cannot safely reference the stashed working-tree changes.","triggerScenarios":"During publishSourceSnapshot, after `git stash push -u` recorded a commit SHA, a later `git stash apply --index <ref>` or cleanup-time `git stash pop` cannot find that SHA in the stash list — typically because the stash was dropped/popped elsewhere (another terminal, `git stash drop/clear`), or the stash list format output changed/was truncated between creation and lookup.","commonSituations":"Developer pops or clears the stash in a parallel terminal while the publish is running; `git gc`/`git stash clear` pruned the stash; running publish on a repo where another tool manages stashes; git versions where the custom --format rendering differs across locales.","solutions":["Check `git stash list` for a stash whose SHA matches the commit printed in the error","If present, apply it manually: `git stash apply --index stash@{N}`, then re-run the publish","If absent, your uncommitted changes were dropped — recover via `git fsck --unrooted` / `git fsck --dangling | grep commit` and inspect dangling commits for the stash","Avoid touching stashes in other terminals while `nb source publish --snapshot` runs"],"exampleFix":"// before: stash vanished mid-publish\nerror: Couldn't locate the saved stash for source publish: 3f9c1ab...\n\n// after: recover dangling stash commit\n$ git fsck --dangling | grep commit\n$ git show <dangling-sha>   # verify it is your stash\n$ git stash apply <dangling-sha>","handlingStrategy":"validation","validationCode":"const stashList = await exec('git stash list --format=%gd%x00%H');\nconst found = stashList.split('\\n').some((l) => l.split('\\u0000')[1]?.trim() === stashCommit);\nif (!found) throw new Error(`Stash ${stashCommit} missing; recover before publishing`);","typeGuard":"function stashExists(stashList: string, commit: string): boolean {\n  return stashList.split('\\n').some((line) => line.split('\\u0000')[1]?.trim() === commit);\n}","tryCatchPattern":"try {\n  await publishSourceSnapshot({ npmRegistry });\n} catch (err) {\n  if (String(err.message).startsWith(\"Couldn't locate the saved stash\")) {\n    console.error('Recover via: git fsck --dangling | grep commit, then git stash apply <sha>');\n  } else throw err;\n}","preventionTips":["Do not run git stash pop/drop/clear in other terminals while a publish is in progress","Run publish with committed changes (stash-free) when possible to avoid stashing entirely","Record the stash SHA output at publish start so you can recover manually","Avoid running git gc --prune=now during a publish"],"tags":["git","stash","cli","source-publish"],"backgroundTag":"stash-entry-not-found","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}