{"record":{"id":"6807d0bebf298ad7","repo":"midudev/autoskills","slug":"could-not-resolve-head-for-repo","errorCode":null,"errorMessage":"could not resolve HEAD for ${repo}","messagePattern":"could not resolve HEAD for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/autoskills/scripts/sync-skills.mjs","lineNumber":192,"sourceCode":"  );\n  if (result.status !== 0) {\n    throw new Error(`git ls-remote failed for ${repo}: ${result.stderr.trim() || \"unknown error\"}`);\n  }\n\n  let defaultBranch = \"main\";\n  let sha = \"\";\n  for (const line of result.stdout.split(\"\\n\")) {\n    const symref = line.match(/^ref:\\s+refs\\/heads\\/(.+)\\s+HEAD$/);\n    if (symref) {\n      defaultBranch = symref[1];\n      continue;\n    }\n    const head = line.match(/^([0-9a-f]{40})\\s+HEAD$/i);\n    if (head) sha = head[1];\n  }\n\n  if (!sha) {\n    throw new Error(`could not resolve HEAD for ${repo}`);\n  }\n\n  return { defaultBranch, sha };\n}\n\nasync function resolveRepoInfo(repo) {\n  const res = await ghFetch(`https://api.github.com/repos/${repo}`);\n  const body = await res.json();\n  return {\n    sizeKB: body.size || 0,\n  };\n}\n\n// Tarball download size threshold (KB). Above this we use per-file fetch.\nconst HEAVY_REPO_KB = 50_000;\n// Hard timeout for tarball downloads. Some repos have slow codeload CDNs.\nconst TARBALL_TIMEOUT_MS = 180_000;\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/midudev/autoskills/blob/0ec725320d2137253ab2e68e7ba8a072148e741a/packages/autoskills/scripts/sync-skills.mjs#L174-L210","documentation":"After a successful `git ls-remote`, resolveRepoHead parses the output lines for a `<40-hex-sha> HEAD` entry to learn the repo's default branch and commit SHA. If no such line is found (sha stays empty), it throws this error. It means the remote answered but its HEAD symref could not be resolved to a commit.","triggerScenarios":"`git ls-remote` output contains no line matching /^([0-9a-f]{40})\\s+HEAD$/i — e.g. the remote returns no HEAD entry, output format is unexpected, or the ls-remote invocation didn't include the HEAD ref (odd server configs, empty repos with no commits).","commonSituations":"Syncing an initialized but completely empty GitHub repo; a git server/proxy that mangles or omits the HEAD symref line; very old or unusual git hosting that doesn't advertise HEAD in ls-remote output.","solutions":["Confirm the repo is not empty (has at least one commit on its default branch)","Run `git ls-remote <url> HEAD` manually and check that a SHA line is printed","Ensure the remote advertises HEAD symrefs (use GitHub or update the hosting/proxy)","Fall back to pinning an explicit branch/SHA instead of relying on HEAD resolution"],"exampleFix":"// before\nconst head = await resolveRepoHead(\"org/empty-repo\"); // throws\n// after\nconst head = await resolveRepoHead(\"org/skills-repo\"); // non-empty repo","handlingStrategy":"validation","validationCode":"// verify the repo advertises a resolvable HEAD\nconst out = execSync(`git ls-remote https://github.com/${repo} HEAD`, { encoding: \"utf8\" });\nif (!/^[0-9a-f]{40}\\s+HEAD$/im.test(out)) {\n  throw new Error(`${repo} has no resolvable HEAD (empty repo?)`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const head = await resolveRepoHead(repo);\n} catch (err) {\n  if (err.message.startsWith(\"could not resolve HEAD\")) {\n    console.error(`Repo ${repo} appears empty or HEAD is not advertised`);\n    // skip repo or fall back to a pinned branch/sha\n  } else throw err;\n}","preventionTips":["Only sync non-empty repos with at least one commit","Prefer GitHub-hosted repos, which always advertise HEAD symrefs","Pin an explicit branch/SHA when HEAD resolution is unreliable","Check ls-remote output manually for unusual git hosts"],"tags":["git","remote","parsing"],"backgroundTag":"unexpected-response-shape","analyzedSha":"0ec725320d2137253ab2e68e7ba8a072148e741a","analyzedAt":"2026-09-15T14:12:31.090Z","contentChangedAt":"2026-09-15T14:12:31.090Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}