ruvnet/ruflo · error
Invalid git ref: too long
Error message
Invalid git ref: too long
What it means
The final stage of validateGitRef(): the ref passed the charset and '..' checks but exceeds 256 characters. Real git refs are bounded (git itself caps refs at ~260 bytes), so anything longer is garbage or an injection attempt even if it is well-formed — the guard rejects it outright.
Solutions
- Trim the input and pass exactly one ref
- Validate length client-side: reject > 256 chars (and empty strings) before calling the library
- Resolve verbose refnames to 40-char SHAs before passing
- Log the offending ref length when this fires — it almost always indicates wrong input upstream, not a legit ref
Example fix
// before
const files = getGitDiffNumstat(rawUserText); // 300-char blob → throws: too long
// after
const ref = rawUserText.trim();
if (!ref || ref.length > 256 || !/^[a-zA-Z0-9_\-./~^@]+$/.test(ref)) {
throw new Error(`invalid git ref: ${JSON.stringify(ref.slice(0, 40))}...`);
}
const files = getGitDiffNumstat(ref); Defensive patterns
Strategy: validation
Validate before calling
function normalizeGitRef(ref: string): string {
const r = (ref ?? '').trim();
if (!r || r.length > 256) throw new Error('git ref must be 1..256 chars');
return r;
} Type guard
const isPlausibleGitRef = (ref: string): boolean => typeof ref === 'string' && ref.length > 0 && ref.length <= 256;
Try / catch
try {
files = getGitDiffNumstat(ref);
} catch (e) {
if (e instanceof Error && e.message.includes('too long')) {
res.status(400).send('git ref too long'); // wrong input shape, not transient
} else throw e;
} Prevention
- Enforce a single-ref, single-line input field for refs in UIs
- Reject > 256 chars at your boundary — legit refs never approach it
- When this fires, log the length: it almost always means wrong data (URL/blob) was passed in
When it happens
Trigger: Passing a pasted git URL ('https://github.com/org/repo.git' plus path), a concatenated ref list ('main dev feat/x release'), base64 or JWT-looking blobs that happen to be alphanumeric, or a ref built by accidental string repetition.
Common situations: UI textareas or generic 'reference' fields piped into diff stats; string concatenation bugs joining several refs; logs or tokens pasted where a ref belongs; copy-paste from issue trackers including formatting.
Related errors
- Invalid git ref: contains unsafe characters
- Invalid git ref: suspicious pattern
- Cannot select from empty array
- Command not allowed
- Invalid argument: contains shell metacharacters
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/f4fc230f7c341964.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/ruvector/diff-classifier.ts:383
/**
* Validate git ref to prevent command injection
* Only allows safe characters: alphanumeric, -, _, /, ., ~, ^
*/
function validateGitRef(ref: string): void {
// Block shell metacharacters and dangerous patterns
if (!/^[a-zA-Z0-9_\-./~^@]+$/.test(ref)) {
throw new Error(`Invalid git ref: contains unsafe characters`);
}
// Block multiple dots (path traversal)
if (ref.includes('..') && !ref.match(/^[a-zA-Z0-9_\-]+\.\.\.?[a-zA-Z0-9_\-]+$/)) {
if (!/^\w+\.\.[.\w]+$/.test(ref)) {
throw new Error(`Invalid git ref: suspicious pattern`);
}
}
// Max length check
if (ref.length > 256) {
throw new Error(`Invalid git ref: too long`);
}
}
/**
* Get git diff statistics using SINGLE combined command (optimized)
* Replaces two separate git commands with one
*/
export function getGitDiffNumstat(ref: string = 'HEAD'): DiffFile[] {
// SECURITY: Validate git ref to prevent command injection
validateGitRef(ref);
// Check cache first
const cacheKey = `numstat:${ref}`;
const cached = diffCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
return cached.files;
}
View on GitHub (pinned to fa13ee4ad6)