thedotmack/claude-mem · warning

Expected JSON array in observation list field, using plain…

Error message

Expected JSON array in observation list field, using plain string fallback

What it means

parseStringListField expects observation list fields (facts/concepts) stored as a JSON array string. If JSON.parse succeeds but yields a non-array, the sync logs this warning and falls back to treating the value as a plain single string (or empty if blank).

Solutions

  1. Normalize the row's field to a JSON array string, e.g. '["value"]' instead of '"value"'.
  2. Identify the writer producing non-array values and fix its serialization.
  3. Rely on the built-in plain-string fallback if the data is a single string — no action needed.
  4. Audit affected rows with SELECT and update malformed values in place.

Example fix

// before (stored value)
"retention: 30 days"
// after (stored value)
["retention: 30 days"]
Defensive patterns

Strategy: validation

Validate before calling

function isJsonArrayString(s: string): boolean {
  try { const p = JSON.parse(s); return Array.isArray(p); } catch { return false; }
}

Type guard

const isStringArray = (v: unknown): v is string[] =>
  Array.isArray(v) && v.every((x) => typeof x === 'string');

Try / catch

try { const parsed = JSON.parse(rawValue); if (!isStringArray(parsed)) { /* fallback to plain string */ } }
catch { /* treat rawValue as plain string */ }

Prevention

When it happens

Trigger: A row's facts/concepts column contains valid JSON that is not an array — e.g. '"single fact"' (JSON string), '{"a":1}' (object), or '42' — instead of '["a","b"]'.

Common situations: Older schema versions stored a plain string; a migration wrote objects; hand-edited SQLite rows; another writer serialized a single value without wrapping it in an array.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/404ef90c8c3bdd97. Report an issue: GitHub.

Appendix: source

Thrown at src/services/sync/ChromaSync.ts:110

  created_at_epoch: number;
  memory_session_id: string;
  project: string;
  platform_source: string;
}

function parseStringListField(
  rawValue: string | null | undefined,
  fieldName: 'facts' | 'concepts',
  rowId: number,
): string[] {
  if (!rawValue) {
    return [];
  }

  try {
    const parsed = JSON.parse(rawValue);
    if (!Array.isArray(parsed)) {
      logger.warn('CHROMA_SYNC', 'Expected JSON array in observation list field, using plain string fallback', {
        fieldName,
        rowId,
        parsedType: typeof parsed,
      });
      if (typeof parsed === 'string') {
        return parsed.trim() ? [parsed] : [];
      }
      return rawValue.trim() ? [rawValue] : [];
    }
    return parsed.filter((value): value is string => typeof value === 'string' && value.trim().length > 0);
  } catch (error) {
    logger.warn('CHROMA_SYNC', 'Malformed observation list field, using plain string fallback', {
      fieldName,
      rowId,
      errorName: error instanceof Error ? error.name : 'NonError',
    });
    return rawValue.trim() ? [rawValue] : [];
  }

View on GitHub (pinned to d8bc9755e7)