santifer/career-ops · error · Error
${describeGitCommand(args)} timed out after ${timeoutSeconds
Error message
${describeGitCommand(args)} timed out after ${timeoutSeconds(timeout)}s. If your network is slow, retry or set ${gitTimeoutEnvVar(args)} to a larger value. What it means
gitIn() runs a git subcommand via execFileSync with a configurable timeout (CAREER_OPS_GIT_TIMEOUT_MS, or CAREER_OPS_GIT_FETCH_TIMEOUT_MS for fetch). If the child does not exit within the timeout, execFileSync kills it and the error is detected as timeout-like; gitIn throws an Error naming the command, the elapsed seconds, and the env var to raise. This prevents update-system.mjs from hanging on a slow network.
Source
Thrown at update-system.mjs:519
function isTimeoutLikeError(err) {
return err?.code === 'ETIMEDOUT' || err?.signal === 'SIGTERM';
}
function timeoutSeconds(timeout) {
return Math.round(timeout / 1000);
}
function gitTimeoutEnvVar(args) {
return args[0] === 'fetch' ? 'CAREER_OPS_GIT_FETCH_TIMEOUT_MS' : 'CAREER_OPS_GIT_TIMEOUT_MS';
}
export function gitIn(root, ...args) {
const timeout = gitTimeoutMs(args);
try {
return execFileSync('git', args, { cwd: root, encoding: 'utf-8', timeout }).trim();
} catch (err) {
if (isTimeoutLikeError(err)) {
throw new Error(`${describeGitCommand(args)} timed out after ${timeoutSeconds(timeout)}s. If your network is slow, retry or set ${gitTimeoutEnvVar(args)} to a larger value.`);
}
throw err;
}
}
function git(...args) {
return gitIn(ROOT, ...args);
}
/**
* git(), but with the child's stderr piped instead of inherited.
*
* execFileSync inherits stderr by default, so a command whose failure is
* expected and handled still prints git's raw error to the console. Use this
* where a non-zero exit is a normal outcome the caller reports itself.
*
* @param {...string} args - git arguments.
* @returns {string} Trimmed stdout.View on GitHub (pinned to 9b17a8ac97)
Solutions
- Raise the timeout via env var: CAREER_OPS_GIT_FETCH_TIMEOUT_MS=300000 node update-system.mjs apply (5 min).
- Check connectivity to the remote: git ls-remote <url> to isolate network vs. auth issues.
- If a credential prompt is hanging, configure a non-interactive credential helper or cache.
- Retry when the network recovers; for a one-time large fetch, run git fetch manually first.
Example fix
# before: default timeout too short for slow link node update-system.mjs apply # -> timed out after 60s # after: raise the fetch timeout CAREER_OPS_GIT_FETCH_TIMEOUT_MS=300000 node update-system.mjs apply
Defensive patterns
Strategy: retry
Validate before calling
function resolveGitTimeout(args) {
return args[0] === 'fetch'
? Number(process.env.CAREER_OPS_GIT_FETCH_TIMEOUT_MS) || 60_000
: Number(process.env.CAREER_OPS_GIT_TIMEOUT_MS) || 60_000;
}
if (resolveGitTimeout(['fetch']) < 120000) {
console.warn('Consider raising CAREER_OPS_GIT_FETCH_TIMEOUT_MS on slow networks');
} Try / catch
try {
await runUpdate();
} catch (err) {
if (err.message.includes('timed out')) {
const m = err.message.match(/set (\S+) to a larger value/);
console.error(`${err.message}\nRetrying with larger timeout.`);
if (m) process.env[m[1]] = String(300000);
await runUpdate();
} else throw err;
} Prevention
- Set CAREER_OPS_GIT_FETCH_TIMEOUT_MS generously in CI and slow-network environments (e.g. 300000).
- Ensure git credential helpers are non-interactive to avoid stdin-block hangs.
- Pre-warm large fetches with a manual `git fetch` outside the timeout-sensitive update path.
When it happens
Trigger: Running update-system.mjs (which calls git fetch/pull/clone) over a slow or stalled network connection that exceeds the default timeout; a hung git credential prompt blocking stdin; an unreachable git remote timing out at TCP level.
Common situations: Slow/constrained network (mobile, throttled CI, cross-continent git host); a credential helper that blocks waiting for input with stdio not inherited; a very large fetch with many objects on a slow link; a temporarily down git hosting provider.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- [models] Failed to fetch free model list: ${reason}. Check t
- Pinned model timed out after ${MODEL_TIMEOUT_MS / 1000}s
- Timeout after ${MODEL_TIMEOUT_MS / 1000}s
- Invalid URL: ${url}
- clone of ${url}@${sha.slice(0, 10)} failed — ${err.stderr ?
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/483a6f7b8ddc0750.
Report an issue: GitHub.