{"record":{"id":"ab744776b631fe41","repo":"affaan-m/ECC","slug":"contextdir-invalid-meta-json-continuing-w","errorCode":null,"errorMessage":"  ! ${contextDir}: invalid meta.json, continuing with defaults (${e.message})","messagePattern":"  ! (.+?): invalid meta\\.json, continuing with defaults \\((.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"skills/ck/commands/migrate.mjs","lineNumber":118,"sourceCode":"      if (existing.version === 2) {\n        console.log(`  ✓ ${contextDir} — already v2, skipping`);\n        skipped++;\n        continue;\n      }\n    } catch { /* fall through to migrate */ }\n  }\n\n  console.log(`\\n  → Migrating: ${contextDir}`);\n\n  try {\n    // Read v1 files\n    const contextMd = existsSync(contextMdPath) ? readFileSync(contextMdPath, 'utf8') : '';\n    let meta = {};\n    if (existsSync(metaPath)) {\n      try {\n        meta = JSON.parse(readFileSync(metaPath, 'utf8'));\n      } catch (e) {\n        console.warn(`  ! ${contextDir}: invalid meta.json, continuing with defaults (${e.message})`);\n      }\n    }\n\n    // Extract fields from CONTEXT.md\n    const description   = extractSection(contextMd, 'What This Is') || extractSection(contextMd, 'About') || null;\n    const stackRaw      = extractSection(contextMd, 'Tech Stack') || '';\n    const stack         = stackRaw.split(/[,\\n]/).map(s => s.replace(/^[-*]\\s+/, '').trim()).filter(Boolean);\n    const goal          = (extractSection(contextMd, 'Current Goal') || '').split('\\n')[0].trim() || null;\n    const constraintRaw = extractSection(contextMd, 'Do Not Do') || '';\n    const constraints   = parseBullets(constraintRaw);\n    const decisionsRaw  = extractSection(contextMd, 'Decisions Made') || '';\n    const decisions     = parseDecisionsTable(decisionsRaw);\n    const nextStepsRaw  = extractSection(contextMd, 'Next Steps') || '';\n    const nextSteps     = parseBullets(nextStepsRaw);\n    const blockersRaw   = extractSection(contextMd, 'Blockers') || '';\n    const blockers      = parseBullets(blockersRaw).filter(b => b.toLowerCase() !== 'none');\n    const leftOffRaw    = extractSection(contextMd, 'Where I Left Off') || '';\n    const leftOffParsed = parseLeftOff(leftOffRaw);","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/ck/commands/migrate.mjs#L100-L136","documentation":"This is not a thrown error but a warning emitted by the CK v1→v2 context migration script in skills/ck/commands/migrate.mjs:118. When a context directory contains a meta.json file that fails JSON.parse (e.g. truncated, hand-edited, or corrupted file), the migration keeps going with an empty `meta` object ({}) so defaults are used for session IDs, dates, and summaries. The migration is deliberately non-fatal: losing v1 metadata is preferable to blocking the whole upgrade.","triggerScenarios":"Running the CK migrate command against a context directory whose meta.json is syntactically invalid JSON — trailing commas, single quotes, BOM bytes, a partially written file, or comments. JSON.parse throws and the catch block prints the warning with the parse error message.","commonSituations":"Manual edits to meta.json that broke syntax; an editor or sync tool truncated the file mid-write; a script appended non-JSON lines; a crash during a previous CK session left a zero-byte or half-written meta.json.","solutions":["Validate the meta.json with `node -e \"JSON.parse(require('fs').readFileSync('<path>','utf8'))\"` to see the exact parse error and line.","Fix the JSON syntax (or restore the file from git/backup), then re-run the migrate command.","If the metadata is not needed, delete meta.json and let the migration proceed with defaults — the warning only means defaults will be substituted.","Check for a BOM or encoding issue: `file meta.json` and re-save as plain UTF-8 without BOM."],"exampleFix":"// before (broken meta.json)\n{ \"lastSessionId\": 'abc123', }\n\n// after\n{ \"lastSessionId\": \"abc123\" }","handlingStrategy":"fallback","validationCode":"const fs = require('fs');\nlet meta = {};\nconst raw = fs.existsSync(metaPath) ? fs.readFileSync(metaPath, 'utf8') : '';\nif (raw) { try { JSON.parse(raw); } catch (e) { console.warn(`meta.json invalid: ${e.message}`); } }","typeGuard":"function isValidMeta(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); }","tryCatchPattern":"let meta = {};\ntry { meta = JSON.parse(readFileSync(metaPath, 'utf8')); }\ncatch (e) { console.warn(`invalid meta.json, using defaults: ${e.message}`); }","preventionTips":["Validate meta.json with a JSON linter before committing or migrating.","Never hand-edit meta.json while a CK session may write to it concurrently.","Back up context directories before running version migrations.","Write meta.json atomically (temp file + rename) in tooling to avoid truncated files."],"tags":["json","migration","parse-error","warning"],"backgroundTag":"json-parse-error","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}