affaan-m/ECC · error · RetrospectiveError
retrospective.invalid_inputs
retrospective.invalid_inputs
Error message
supply 1 to ${MAX_INPUTS} capsule directory paths What it means
groupCapsules validates its input list before doing any work: it must be an array of 1 to MAX_INPUTS non-empty strings with no NUL bytes. Anything else — an empty array, a non-array, too many directories, or entries that are not clean non-empty strings — is rejected with this error before any capsule is read.
Solutions
- Ensure the array contains between 1 and MAX_INPUTS string paths before calling
- Check the glob/command that produces the list actually matched capsule directories
- Trim and filter the list: dirs.filter(d => typeof d === 'string' && d.trim())
- Split oversized batches into multiple groupCapsules invocations
Example fix
// before await groupCapsules(foundDirs) // foundDirs may be [] // after const clean = foundDirs.filter(d => typeof d === 'string' && d.trim()); if (clean.length >= 1 && clean.length <= MAX_INPUTS) await groupCapsules(clean);
Defensive patterns
Strategy: validation
Validate before calling
function validateDirs(dirs) { return Array.isArray(dirs) && dirs.length >= 1 && dirs.length <= MAX_INPUTS && dirs.every(d => typeof d === 'string' && d.trim() && !d.includes('\0')); }
if (!validateDirs(dirs)) throw new Error('groupCapsules needs 1..MAX_INPUTS non-empty string paths'); Type guard
const isCapsuleDirList = (v) => Array.isArray(v) && v.length >= 1 && v.every((d) => typeof d === 'string' && d.trim().length > 0);
Try / catch
try { groupCapsules(dirs); } catch (e) { if (e.code === 'retrospective.invalid_inputs') console.error('check the glob that produced the dir list; expected 1..MAX_INPUTS clean strings'); throw e; } Prevention
- Check glob expansion results before invoking (a glob matching nothing yields [])
- Filter/trim the directory list before passing it
- Keep batch sizes within MAX_INPUTS and split larger sets
- Quote shell arguments to avoid stray bytes in paths
When it happens
Trigger: Calling groupCapsules([]), groupCapsules('dir'), groupCapsules with more than MAX_INPUTS paths, or an array containing null/undefined/empty-string/whitespace-only entries or paths containing '\0'.
Common situations: Shell globbing that expands to zero files on a fresh checkout; a CLI wrapper passing undefined when no arguments were given; scripted batch runs accumulating more capsule directories than MAX_INPUTS allows; trailing NUL bytes from exec-style argument handling.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- all overlays must be readable local files
- all takes must be readable local files
- application request must be a JSON object
- base video must be a readable local file
- -32602
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/11e942ce9561dfd0.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/eval-harness/retrospective.js:67
by_effect_class: byEffect,
sources: [...projections].sort((a, b) => compare(identity(a), identity(b)))
.map(item => ({
identity_hash: hashValue([item.run_id, item.capsule_id]),
...Object.fromEntries(SOURCE_FIELDS.map(key => [key, item[key]])),
})),
};
}
/**
* Group up to 100 selected snapshots of one task family by harness_version.
* Duplicate identities count once only if the verified projections match.
* Different checkpoints of the same identity are ambiguous and refused.
* Does not read saved projections, copy payloads, write files or invoke tools.
*/
function groupCapsules(dirs) {
if (!Array.isArray(dirs) || dirs.length < 1 || dirs.length > MAX_INPUTS
|| !Array.from(dirs).every(dir => typeof dir === 'string' && dir.trim() && !dir.includes('\0'))) {
throw new RetrospectiveError('retrospective.invalid_inputs', `supply 1 to ${MAX_INPUTS} capsule directory paths`);
}
const projections = dirs.map(readProjection);
const family = projections[0].task_family;
const unique = new Map();
for (const [index, projection] of projections.entries()) {
if (projection.task_family !== family) {
throw new RetrospectiveError('retrospective.mixed_task_families', 'all capsules must have the same task family', index);
}
const key = identity(projection);
const previous = unique.get(key);
if (previous && previous.projection_hash !== projection.projection_hash) {
throw new RetrospectiveError('retrospective.conflicting_identity', 'conflicting snapshots share a capsule identity', index);
}
unique.set(key, projection);
}
const byHarness = new Map();
for (const projection of unique.values()) {
const version = projection.harness_version;View on GitHub (pinned to 8321021c54)