{"record":{"id":"02cc64179100fd4a","repo":"affaan-m/ECC","slug":"invalid-label-expected-json-compatible-data","errorCode":null,"errorMessage":"Invalid ${label}: expected JSON-compatible data","messagePattern":"Invalid (.+?): expected JSON-compatible data","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install-lifecycle.js","lineNumber":276,"sourceCode":"\nfunction parseJsonLikeValue(value, label) {\n  if (value === undefined) {\n    return undefined;\n  }\n\n  if (typeof value === 'string') {\n    try {\n      return JSON.parse(value);\n    } catch (error) {\n      throw new Error(`Invalid ${label}: ${error.message}`);\n    }\n  }\n\n  if (value === null || Array.isArray(value) || isPlainObject(value) || typeof value === 'number' || typeof value === 'boolean') {\n    return cloneJsonValue(value);\n  }\n\n  throw new Error(`Invalid ${label}: expected JSON-compatible data`);\n}\n\nfunction getOperationTextContent(operation) {\n  const candidateKeys = ['renderedContent', 'content', 'managedContent', 'expectedContent', 'templateOutput'];\n\n  for (const key of candidateKeys) {\n    if (typeof operation[key] === 'string') {\n      return operation[key];\n    }\n  }\n\n  return null;\n}\n\nfunction getOperationJsonPayload(operation) {\n  const candidateKeys = ['mergePayload', 'managedPayload', 'payload', 'value', 'expectedValue'];\n\n  for (const key of candidateKeys) {","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install-lifecycle.js#L258-L294","documentation":"After handling undefined and strings, parseJsonLikeValue accepts null, arrays, plain objects, numbers, and booleans as JSON-compatible values. Any other JavaScript type (function, symbol, bigint, class instance, Date) cannot be safely serialized into the managed settings file, so the library throws. The message is generic; the label used by callers identifies the offending operation field.","triggerScenarios":"getOperationJsonPayload or getOperationPreviousJson encounters a non-undefined value at mergePayload/managedPayload/payload/value/expectedValue or previousValue/previousJson/originalValue that is not a string, null, array, plain object, number, or boolean — e.g. a Date, Map, Set, class instance (like a custom config object), or function passed into the operation programmatically.","commonSituations":"Programmatically building install operations in a script and passing a Date or config-class instance where a plain JSON value is required; state loaded through a deserializer that revives values into class instances instead of plain objects.","solutions":["Convert the offending value to a plain JSON-compatible structure before passing it (e.g. date.toISOString(), Object.fromEntries(map), plain object literal).","Ensure operation objects are built from JSON.parse/structuredClone-safe data, not class instances.","Check the value named by the error label and wrap it with a small normalize step that strips or converts non-JSON types recursively.","If a Date-like value was intended, store it as an ISO 8601 string."],"exampleFix":"// before\n{ kind: 'update-claude-settings', payload: { updatedAt: new Date() } }\n\n// after\n{ kind: 'update-claude-settings', payload: { updatedAt: new Date().toISOString() } }","handlingStrategy":"type-guard","validationCode":"function assertJsonCompatible(value) {\n  if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return;\n  if (Array.isArray(value)) return value.forEach(assertJsonCompatible);\n  if (value && typeof value === 'object' && value.constructor === Object) {\n    return Object.values(value).forEach(assertJsonCompatible);\n  }\n  throw new Error('Non-JSON value in payload');\n}","typeGuard":"const isPlainJsonValue = v =>\n  v === null || ['string', 'number', 'boolean'].includes(typeof v) ||\n  (Array.isArray(v) && v.every(isPlainJsonValue)) ||\n  (v !== null && typeof v === 'object' && v.constructor === Object && Object.values(v).every(isPlainJsonValue));","tryCatchPattern":"try {\n  await applyOperation(op);\n} catch (err) {\n  if (/expected JSON-compatible data/.test(err.message)) {\n    console.error('Convert Dates/Maps/class instances to plain JSON before building the operation.');\n  } else throw err;\n}","preventionTips":["Round-trip payloads through JSON.parse(JSON.stringify(x)) (or structuredClone after serialization) to strip non-JSON types.","Serialize Dates as ISO strings at the boundary where operations are built.","Avoid passing class instances from config loaders directly as operation payloads."],"tags":["json","type-mismatch","state"],"backgroundTag":"schema-validation-failed","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"}