affaan-m/ECC · error · Error

memory must be an object.

Error message

memory must be an object.

What it means

normalizeMemory() validates that the memory argument passed to save/normalize is a plain, non-null, non-array object before applying field-level validation. The memory vault format requires an object mapping named fields (schema, id, title, targetHarnesses, etc.), so anything else — null, undefined, strings, arrays — is rejected early with this clear message instead of producing cryptic failures downstream.

Solutions

  1. Wrap the memory payload in an object literal with the required fields (schema, id, title, targetHarnesses, ...).
  2. Check the input source: if it came from JSON.parse, confirm the top-level value is an object, not an array or scalar.
  3. Add a guard before the call: if (!memory || typeof memory !== 'object' || Array.isArray(memory)) handle the error case.
  4. If using `null` as a sentinel for 'no memory', branch before calling normalize instead of passing null through.

Example fix

// before
const memory = await loadMemory();
await saveMemory(memory); // loadMemory() may return null

// after
const memory = await loadMemory() ?? { schema: MEMORY_SCHEMA_VERSION, id: 'default', title: 'Untitled', targetHarnesses: ['all'] };
if (memory && typeof memory === 'object' && !Array.isArray(memory)) {
  await saveMemory(memory);
}
Defensive patterns

Strategy: type-guard

Validate before calling

function isPlainObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }
if (!isPlainObject(input)) throw new TypeError('memory payload must be a plain object');

Type guard

const isMemoryInput = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);

Try / catch

try {
  const memory = normalizeMemory(input);
} catch (err) {
  if (err.message === 'memory must be an object.') {
    console.error('Refusing to save: memory payload is not an object (got %s).', input === null ? 'null' : typeof input);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling normalizeMemory (directly or via normalizeSaveInput / parseMemoryDocument callers / normalized) with null, undefined, a string, a number, an array (e.g. JSON.parse('[...]')), or a Map/Set instead of a plain object.

Common situations: Piping JSON output from another tool where the top level is an array; forgetting to await a promise so a non-object flows in; passing null as a default; destructuring mistakes that yield undefined; scripts that read an empty file and pass '' as the memory.

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


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/437fec94758fd1a2. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/memory-vault-format.js:163

  if (typeof value !== 'string') {
    throw new Error('memory body must be a string.');
  }
  if (hasUnsafeControlCharacters(value, true)) {
    throw new Error('memory body must not contain unsafe control or bidirectional formatting characters.');
  }
  const normalized = value.trim();
  if (normalized.length === 0) {
    throw new Error('memory body must contain non-whitespace context.');
  }
  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),

View on GitHub (pinned to 8321021c54)