{"record":{"id":"c4517e38f0618425","repo":"facebook/docusaurus","slug":"command-returned-unexpected-exitcode-result-exit","errorCode":null,"errorMessage":"Command returned unexpected exitCode ${result.exitCode}","messagePattern":"Command returned unexpected exitCode (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/docusaurus/src/commands/deploy.ts","lineNumber":50,"sourceCode":"// for example: https://github.com/facebook/docusaurus/issues/3875\nfunction exec(cmd: string, options?: {log?: boolean; failfast?: boolean}) {\n  const log = options?.log ?? true;\n  const failfast = options?.failfast ?? false;\n  try {\n    // TODO migrate to execa(file,[...args]) instead\n    //  Use async/await everything\n    //  Avoid execa.command: the args need to be escaped manually\n    const result = execa.commandSync(cmd);\n    if (log || debugMode) {\n      logger.info`code=${obfuscateGitPass(\n        cmd,\n      )} subdue=${`code: ${result.exitCode}`}`;\n    }\n    if (debugMode) {\n      console.log(result);\n    }\n    if (failfast && result.exitCode !== 0) {\n      throw new Error(\n        `Command returned unexpected exitCode ${result.exitCode}`,\n      );\n    }\n    return result;\n  } catch (err) {\n    throw new Error(\n      logger.interpolate`Error while executing command code=${obfuscateGitPass(\n        cmd,\n      )}\nIn CWD code=${process.cwd()}`,\n      {cause: err},\n    );\n  }\n}\n\n// Execa escape args and add necessary quotes automatically\n// When using Execa.command, the args containing spaces must be escaped manually\nfunction escapeArg(arg: string): string {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus/src/commands/deploy.ts#L32-L68","documentation":"Thrown by the deploy command's internal `exec` helper when failfast is true and a command returned a non-zero exitCode. The offending command and its code are already logged before the throw. Used for critical git probes in deploy (e.g. `git remote get-url origin`, `git rev-parse --abbrev-ref HEAD`).","triggerScenarios":"Any failfast exec returning non-zero during deploy: missing 'origin' remote, detached HEAD with no CURRENT_BRANCH set, or git refusing an operation (auth, permissions).","commonSituations":"Repo with no `origin` remote configured, shallow/detached HEAD in CI without CURRENT_BRANCH env, or git authentication failures on the source remote.","solutions":["Reproduce the exact logged command manually to see the underlying git error.","For missing origin: `git remote add origin <url>`.","For detached HEAD in CI: set the CURRENT_BRANCH env var to the deploying branch.","Ensure git credentials/SSH agent are available for any authenticated remote operation."],"exampleFix":"# before\n# deploy fails: `git remote get-url origin` exitCode=128\n# after\ngit remote add origin git@github.com:org/repo.git\ndocusaurus deploy","handlingStrategy":"try-catch","validationCode":"import {execSync} from 'child_process';\nfunction preflight(cmd: string, cwd = process.cwd()) {\n  execSync(cmd, {cwd, stdio: 'pipe'}); // throws before deploy if it would fail\n}","typeGuard":null,"tryCatchPattern":"try {\n  exec('git remote get-url origin', {log: false, failfast: true});\n} catch (e) {\n  if (/unexpected exitCode/.test(String(e))) repairOriginRemote();\n  else throw e;\n}","preventionTips":["Set CURRENT_BRANCH in CI to avoid detached-HEAD failures.","Ensure `origin` remote exists before deploying.","Reproduce each failfast command manually first."],"tags":["deploy","git","cli","exit-code"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}