affaan-m/ECC · error · Error
message
Error message
message
What it means
parseMemoryDocument parses a memory-vault document's YAML-ish frontmatter, which must be delimited by an opening and a closing '---' marker. After locating the opening marker, it searches the remainder of the source with the regex /\r?\n---(?=\r?\n|$)/; if no closing marker line exists anywhere, it throws this error. The library throws it to avoid silently treating the entire document (including intended body text) as unterminated frontmatter.
Solutions
- Open the document at sourcePath and add a closing '---' line on its own line right after the last frontmatter field.
- Verify the closing marker is exactly '---' with no leading whitespace, trailing characters, or extra dashes ('----' does not match).
- Ensure there is a newline before the closing marker ('\n---'); a marker glued to the last field line will not match.
- Re-obtain or regenerate the corrupted document if the file was truncated (e.g. restore from git or rewrite via the library's save API).
Example fix
// before (broken memory document) --- title: session note scope: project // after --- title: session note scope: project --- Body text goes here.
Defensive patterns
Strategy: validation
Validate before calling
function hasClosingFrontmatterMarker(source) {
return typeof source === 'string'
&& /^---/.test(source.trimStart())
&& /\r?\n---(\r?\n|$)/.test(source);
}
if (!hasClosingFrontmatterMarker(raw)) throw new Error('Document is missing a closing --- frontmatter marker'); Type guard
const isDelimitedMemoryDoc = (s) => typeof s === 'string' && /^---[\s\S]*\r?\n---(\r?\n|$)/.test(s);
Try / catch
try {
const doc = parseMemoryDocument(source, sourcePath);
} catch (err) {
if (err.message.includes('no closing frontmatter marker')) {
// surface file path + line hint to user, offer to regenerate template
} else throw err;
} Prevention
- Always create memory documents from the library's save/template API instead of hand-writing frontmatter.
- Keep the closing '---' on its own line with no indentation or trailing characters.
- Lint vault files in CI with a delimiter check to catch truncated or hand-edited docs early.
- Avoid editors/tools that strip trailing newlines or trailing whitespace from vault files.
When it happens
Trigger: Calling parseMemoryDocument (directly or via memory/parsed helpers) with a source string whose frontmatter is opened with '---' but never terminated by a line containing exactly '---' followed by a newline or end-of-file. Examples: truncated file, missing final newline with trailing content not matching the lookahead, frontmatter commented out, or a closing marker indented or written as '--- ' or '----'.
Common situations: A memory document was hand-edited and the closing '---' deleted; a file got truncated by a failed write or interrupted sync; an editor or tool stripped trailing newlines/added trailing spaces to the marker; a user pasted only the frontmatter header into a new vault file; Windows/Unix newline mangling producing '\r\n---\r' handled incorrectly after copying between OSes.
Related errors
- ECC_PROJECT_DIR must be an absolute path within /workspace.
- Cannot adapt Antigravity agent
- Cannot adapt Antigravity agent
- Cannot merge ECC configuration into invalid JSON at
- ! : invalid meta.json, continuing with defaults ( )
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/feb7ba175e4df570.
Report an issue: GitHub.
Appendix: source
Thrown at docker/plugin-setup/prepare-packed-cli.js:20
'use strict';
const { spawnSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const EXPECTED_NAME = 'ecc-universal';
const EXPECTED_BIN = 'scripts/ecc.js';
const CHILD_PROCESS_TIMEOUT_MS = 5 * 60 * 1000;
const REQUIRED_FILES = Object.freeze([
'scripts/ecc.js',
'manifests/install-components.json',
'manifests/install-modules.json',
'manifests/install-profiles.json',
]);
function fail(message) {
throw new Error(message);
}
function isWithin(root, candidate) {
const relative = path.relative(root, candidate);
return relative === '' || (
relative !== '..'
&& !relative.startsWith(`..${path.sep}`)
&& !path.isAbsolute(relative)
);
}
function requireRegularFile(packageRoot, relativePath) {
const resolvedPath = path.resolve(packageRoot, relativePath);
if (!isWithin(packageRoot, resolvedPath)) {
fail(`Package path escapes the extracted root: ${relativePath}`);
}
let file;
try {View on GitHub (pinned to 8321021c54)