affaan-m/ECC · error · Error
target harnesses must contain at least one harness or "all".
Error message
target harnesses must contain at least one harness or "all".
What it means
Thrown by normalizeMemory() after uniqueStrings() succeeds when memory.targetHarnesses.length === 0. Each memory must declare which agent harnesses should see it (e.g. 'claude', 'codex', 'cursor') or use the literal 'all'. An empty array would make the memory invisible to every consumer and is therefore rejected as a programming mistake rather than silently stored.
Source
Thrown at scripts/lib/memory-vault-format.js:172
}
if (Buffer.byteLength(normalized, 'utf8') > MAX_BODY_BYTES) {
throw new Error(`memory body is too large (maximum ${MAX_BODY_BYTES} bytes).`);
}
return normalized;
}
function normalizeMemory(memory) {
if (!memory || typeof memory !== 'object' || Array.isArray(memory)) {
throw new Error('memory must be an object.');
}
const targetHarnesses = uniqueStrings(memory.targetHarnesses, {
label: 'target harnesses',
limit: MAX_TARGETS,
validator: value => validateSlug(value, 'target harness'),
});
if (targetHarnesses.length === 0) {
throw new Error('target harnesses must contain at least one harness or "all".');
}
if (memory.schema !== MEMORY_SCHEMA_VERSION) {
throw new Error('Unsupported memory schema.');
}
return {
schema: memory.schema,
id: validateMemoryId(memory.id),
title: asNonEmptyString(memory.title, 'memory title', MAX_TITLE_CHARS),
kind: validateEnum(memory.kind, MEMORY_KINDS, 'memory kind'),
scope: validateEnum(memory.scope, MEMORY_SCOPES, 'memory scope'),
trust: validateEnum(memory.trust, MEMORY_TRUST_STATES, 'memory trust'),
status: validateEnum(memory.status, MEMORY_STATUSES, 'memory status'),
sourceHarness: validateSlug(memory.sourceHarness, 'source harness'),
targetHarnesses,
tags: uniqueStrings(memory.tags, {
label: 'tags',View on GitHub (pinned to 01e15490f0)
Solutions
- Default to ['all'] when no specific harness is requested: targetHarnesses: input.targetHarnesses?.length ? input.targetHarnesses : ['all'].
- Validate at the form/CLI boundary: refuse to proceed if the user selected zero harnesses.
- Prefer saveMemory() which already defaults targetHarnesses to ['all'] when input.targetHarnesses is absent.
- If you call normalizeMemory() directly, always set the field explicitly.
Example fix
// before
saveMemory({
title: 'pref',
body: '...'
// targetHarnesses omitted entirely in custom path
});
// after
saveMemory({
title: 'pref',
body: '...',
targetHarnesses: input.target?.length ? input.target : ['all']
}); Defensive patterns
Strategy: validation
Validate before calling
const targetHarnesses = Array.isArray(input.targetHarnesses) && input.targetHarnesses.length > 0
? input.targetHarnesses
: ['all'];
saveMemory({ ...input, targetHarnesses }); Type guard
function hasValidTargets(value): value is string[] {
return Array.isArray(value) && value.length > 0
&& value.every(v => typeof v === 'string' && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(v));
} Prevention
- Default to ['all'] in your wrapper when the caller supplies no target harnesses.
- Build targetHarnesses via filter then assert length > 0.
- Let saveMemory() apply its own default by omitting the field entirely.
When it happens
Trigger: saveMemory({targetHarnesses: []}), saveMemory({}) when the caller omitted targetHarnesses and the defaulting layer did not supply ['all'], or saveMemory({targetHarnesses: undefined}) where normalizeSaveInput did NOT apply its default because input was passed through unchanged.
Common situations: Wrapper that builds targetHarnesses from a filter without checking the result is non-empty. CLI that takes --target as a repeatable flag but received zero repetitions. Migration script that copies targetHarnesses from an old schema where the field was optional.
Related errors
- memory body must contain non-whitespace context.
- Memory document ${sourcePath} is missing fields: ${missing.j
- --title is required.
- At least one guided harness must be selected
- The all/* harness selection cannot be combined with other se
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/6135814ff536448f.
Report an issue: GitHub.