{"record":{"id":"aa13888af9876f9c","repo":"thedotmack/claude-mem","slug":"generation-parse-error-outcome-reason","errorCode":null,"errorMessage":"generation parse error: ${outcome.reason}","messagePattern":"generation parse error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/server/generation/ProviderObservationGenerator.ts","lineNumber":262,"sourceCode":"      apiKeyId: payload.api_key_id,\n      actorId: payload.actor_id,\n      sourceAdapter: payload.source_adapter,\n      ...(this.options.workerId !== undefined ? { workerId: this.options.workerId } : {}),\n    };\n    const outcome: ProcessGeneratedResponseOutcome = fresh.sourceType === 'session_summary'\n      ? await processSessionSummaryResponse(persistInput)\n      : await processGeneratedResponse(persistInput);\n\n    if (outcome.kind === 'parse_error') {\n      await markGenerationFailed({\n        pool: this.options.pool,\n        job: fresh,\n        reason: outcome.reason,\n        classification: 'parse_error',\n        retryable: false,\n        ...(this.options.workerId !== undefined ? { workerId: this.options.workerId } : {}),\n      });\n      throw new Error(`generation parse error: ${outcome.reason}`);\n    }\n\n    logger.info('SYSTEM', 'generation completed', {\n      correlationId,\n      jobId: outcome.jobId,\n      bullmqJobId: job.id ?? null,\n      requestId: payloadRequestId,\n      observationCount: outcome.observations.length,\n      privateContentDetected: outcome.privateContentDetected,\n    });\n\n    return {\n      jobId: outcome.jobId,\n      status: 'completed',\n      observationCount: outcome.observations.length,\n    };\n  }\n","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/server/generation/ProviderObservationGenerator.ts#L244-L280","documentation":"When generating folder-level CLAUDE.md files, the code JSON.parses the CLAUDE_MEM_FOLDER_MD_EXCLUDE settings string, expecting a JSON array of glob strings (default '[]'). The parse threw — the setting is present but not valid JSON (e.g. a bare comma-separated list). The handler warns under FOLDER_INDEX and continues with an empty exclude list, so every folder gets folder-md treatment.","triggerScenarios":"Setting CLAUDE_MEM_FOLDER_MD_EXCLUDE=dist,build instead of [\"dist\",\"build\"]; unbalanced quotes or trailing commas; shell quoting mangling the value when exporting in a dotfile or CI.","commonSituations":"Hand-editing .claude-mem settings; copying an example with smart quotes from docs/chat; CI environment variables losing inner quotes.","solutions":["Write the value as a JSON array string: CLAUDE_MEM_FOLDER_MD_EXCLUDE=[\"node_modules\",\"dist\",\"build\"]","Validate before running: `node -e 'JSON.parse(process.argv[1])' 'your-value'` must exit cleanly.","Leave the setting unset to use the empty default rather than writing malformed values.","Apply the same fix to CLAUDE_MEM_FOLDER_MD_SKELETON_DENYLIST, which fails identically one block later."],"exampleFix":"# before\nCLAUDE_MEM_FOLDER_MD_EXCLUDE=dist,build\n\n# after\nCLAUDE_MEM_FOLDER_MD_EXCLUDE=[\"dist\",\"build\"]","handlingStrategy":"validation","validationCode":"// Validate list-shaped settings BEFORE the pipeline that consumes them\nfunction parseJsonStringArray(raw: string | undefined, name: string): string[] {\n  if (!raw) return [];\n  try {\n    const parsed: unknown = JSON.parse(raw);\n    if (Array.isArray(parsed) && parsed.every(p => typeof p === 'string')) return parsed;\n  } catch { /* fall through */ }\n  throw new Error(`${name} must be a JSON array of strings, got: ${raw}`);\n}\n\nconst folderMdExcludePaths = parseJsonStringArray(settings.CLAUDE_MEM_FOLDER_MD_EXCLUDE, 'CLAUDE_MEM_FOLDER_MD_EXCLUDE');","typeGuard":"function isStringArray(value: unknown): value is string[] {\n  return Array.isArray(value) && value.every(v => typeof v === 'string');\n}","tryCatchPattern":null,"preventionTips":["Always write these settings as JSON array literals: [\"a\",\"b\"], never comma-separated lists.","Add a settings lint step (`node -e 'JSON.parse(v)'`) to startup or CI for every *_EXCLUDE-style variable.","Quote env values in shells so inner double quotes survive: export X='[\"dist\",\"build\"]'."],"tags":["settings","json-parse","folder-index","configuration","claude-md"],"backgroundTag":"malformed-json-setting","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","contentChangedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}