affaan-m/ECC · error · Error

memory search query must not contain control characters.

Error message

memory search query must not contain control characters.

What it means

searchMemories rejects queries containing unsafe control characters (e.g. raw newlines, null bytes, escape sequences) via hasUnsafeControlCharacters. This prevents control-character injection into search processing and log/output corruption.

Solutions

  1. Strip control characters from the query before calling searchMemories.
  2. Collapse whitespace: replace newlines/tabs with spaces.
  3. Sanitize any programmatic input source before it reaches the query parameter.

Example fix

// before
searchMemories(rawClipboardText);
// after
const query = rawClipboardText.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '').replace(/\s+/g, ' ').trim();
searchMemories(query);
Defensive patterns

Strategy: validation

Validate before calling

const hasUnsafeControlChars = (s) => /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(s);
if (hasUnsafeControlChars(query)) query = query.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, ' ').replace(/\s+/g, ' ').trim();

Type guard

const isCleanQuery = (q) => typeof q === 'string' && !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(q);

Try / catch

try {
  searchMemories(query);
} catch (err) {
  if (err.message.includes('control characters')) {
    searchMemories(sanitizeQuery(query));
  } else throw err;
}

Prevention

When it happens

Trigger: Calling searchMemories with a query containing control characters — often from copying multiline text, binary-ish input, or untrimmed terminal paste content into the query string.

Common situations: Pasting multi-line text (newlines/tabs count depending on the unsafe set) into a CLI search prompt; programmatic input from files or network responses not sanitized before search.

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/d4896ea5aaa61258. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/memory-vault.js:608

  const start = Math.max(0, (matchIndex < 0 ? 0 : matchIndex) - 60);
  const prefix = start > 0 ? '…' : '';
  const suffix = start + maxChars < normalized.length ? '…' : '';
  return `${prefix}${normalized.slice(start, start + maxChars)}${suffix}`;
}

function summarizeMemory(memory) {
  return Object.fromEntries(
    Object.entries(memory).filter(([key]) => key !== 'body')
  );
}

function searchMemories(query, options = {}) {
  const normalizedQuery = typeof query === 'string' ? query.trim() : '';
  if (normalizedQuery.length > MAX_QUERY_CHARS) {
    throw new Error(`memory search query is too long (maximum ${MAX_QUERY_CHARS} characters).`);
  }
  if (hasUnsafeControlCharacters(normalizedQuery)) {
    throw new Error('memory search query must not contain control characters.');
  }

  const kinds = options.kinds
    ? uniqueStrings(options.kinds, {
      label: 'kinds',
      limit: MEMORY_KINDS.length,
      validator: value => validateEnum(value, MEMORY_KINDS, 'memory kind'),
    })
    : null;
  const trust = options.trust
    ? validateEnum(options.trust, MEMORY_TRUST_STATES, 'memory trust')
    : null;
  const targetHarness = options.targetHarness
    ? validateSlug(options.targetHarness, 'target harness')
    : null;
  const limit = Math.max(1, Math.min(Number(options.limit) || 20, MAX_RESULTS));
  const loaded = readMemoryFiles({ ...options, scopes: options.scopes || options.scope });

View on GitHub (pinned to 8321021c54)