affaan-m/ECC · warning
! ${contextDir}: invalid meta.json, continuing with defaul
Error message
! ${contextDir}: invalid meta.json, continuing with defaults (${e.message}) What it means
During the ck context-dir v1->v2 migration (skills/ck/commands/migrate.mjs), each directory may carry a v1 meta.json sidecar. If readFileSync succeeds but JSON.parse throws (syntax error, empty file, BOM, merge-conflict markers), the migrator prints this warning and continues with `meta = {}` defaults, deriving everything else from CONTEXT.md sections instead. It is non-fatal by design, but metadata that lived only in meta.json is silently lost.
Source
Thrown at skills/ck/commands/migrate.mjs:118
if (existing.version === 2) {
console.log(` ✓ ${contextDir} — already v2, skipping`);
skipped++;
continue;
}
} catch { /* fall through to migrate */ }
}
console.log(`\n → Migrating: ${contextDir}`);
try {
// Read v1 files
const contextMd = existsSync(contextMdPath) ? readFileSync(contextMdPath, 'utf8') : '';
let meta = {};
if (existsSync(metaPath)) {
try {
meta = JSON.parse(readFileSync(metaPath, 'utf8'));
} catch (e) {
console.warn(` ! ${contextDir}: invalid meta.json, continuing with defaults (${e.message})`);
}
}
// Extract fields from CONTEXT.md
const description = extractSection(contextMd, 'What This Is') || extractSection(contextMd, 'About') || null;
const stackRaw = extractSection(contextMd, 'Tech Stack') || '';
const stack = stackRaw.split(/[,\n]/).map(s => s.replace(/^[-*]\s+/, '').trim()).filter(Boolean);
const goal = (extractSection(contextMd, 'Current Goal') || '').split('\n')[0].trim() || null;
const constraintRaw = extractSection(contextMd, 'Do Not Do') || '';
const constraints = parseBullets(constraintRaw);
const decisionsRaw = extractSection(contextMd, 'Decisions Made') || '';
const decisions = parseDecisionsTable(decisionsRaw);
const nextStepsRaw = extractSection(contextMd, 'Next Steps') || '';
const nextSteps = parseBullets(nextStepsRaw);
const blockersRaw = extractSection(contextMd, 'Blockers') || '';
const blockers = parseBullets(blockersRaw).filter(b => b.toLowerCase() !== 'none');
const leftOffRaw = extractSection(contextMd, 'Where I Left Off') || '';
const leftOffParsed = parseLeftOff(leftOffRaw);View on GitHub (pinned to d8409a4b08)
Solutions
- Locate the parse error precisely: node -e "JSON.parse(require('fs').readFileSync('meta.json','utf8'))" from the context dir.
- Fix the JSON (remove comments/trailing commas, resolve conflict markers, re-save without BOM) and re-run the migration for that directory.
- If the file is intentionally empty or meaningless, delete it — absence is handled without a warning.
- After a defaulted migration, re-add any metadata that mattered; it was not carried over.
Example fix
before (meta.json):
{ "tags": ["a", "b",], } // trailing comma + comment -> warning, defaults used
after:
{ "tags": ["a", "b"] } Defensive patterns
Strategy: fallback
Validate before calling
import { readFileSync } from 'node:fs';
function parseMeta(p) {
try {
return { ok: true, meta: JSON.parse(readFileSync(p, 'utf8')) };
} catch (e) {
return { ok: false, error: e.message };
}
}
// before migrating a context dir, surface bad files instead of silently defaulting:
const r = parseMeta(metaPath);
if (!r.ok) console.error(`${contextDir}: fix meta.json first (${r.error})`); Type guard
function isPlainObject(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Try / catch
let meta = {};
try {
meta = JSON.parse(readFileSync(metaPath, 'utf8'));
} catch (e) {
console.warn(` ! ${contextDir}: invalid meta.json, continuing with defaults (${e.message})`);
// optionally: record contextDir in a repair list to fix after the batch run
} Prevention
- Run `npx jsonlint` (or `node -e "JSON.parse(...)"`) over meta.json files before migrations.
- Use a JSON-aware editor/prettier so comments, trailing commas, and BOM never creep in.
- Resolve git merge conflicts in JSON files instead of committing markers.
- After any migration that printed this warning, diff the migrated output against the original meta.json to recover dropped metadata.
When it happens
Trigger: Hand-edited meta.json containing comments, single quotes, or trailing commas; empty or truncated files; git merge conflicts leaving <<<<<<< / >>>>>>> markers; files saved as UTF-8 with BOM which JSON.parse rejects.
Common situations: Legacy contexts edited in editors without JSON validation; migration runs over many dirs where one bad file warns and proceeds; users surprised that migrated contexts lack original metadata because defaults were used.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- gh ${args.join(' ')} returned invalid JSON: ${error.message}
- Failed to load policy from ${resolvedPath}: ${error.message}
- empty stdin
- Unknown argument: ${arg}
- Invalid ECC repo root: unreadable package.json at ${packageJ
AI-assisted analysis of affaan-m/ECC@d8409a4b08 (2026-08-26).
Data as JSON: /api/errors/ab744776b631fe41.
Report an issue: GitHub.