{"record":{"id":"5cc881208ffac7ce","repo":"linshenkx/prompt-optimizer","slug":"favorite-metadata-cannot-contain-inline-image-data","errorCode":null,"errorMessage":"Favorite metadata cannot contain inline image data URLs (${path})","messagePattern":"Favorite metadata cannot contain inline image data URLs \\((.+?)\\)","errorType":"validation","errorClass":"FavoriteValidationError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/favorite/storage-guards.ts","lineNumber":80,"sourceCode":"    new Set(\n      value\n        .map((tag) => (typeof tag === 'string' ? tag.trim() : ''))\n        .filter(Boolean),\n    ),\n  )\n}\n\nexport const getSerializedByteLength = (value: string): number =>\n  TEXT_ENCODER.encode(value).byteLength\n\nexport const assertFavoriteMetadataHasNoInlineImages = (\n  value: unknown,\n  path = 'metadata',\n  seen: WeakSet<object> = new WeakSet(),\n): void => {\n  if (typeof value === 'string') {\n    if (INLINE_IMAGE_DATA_URL_RE.test(value.trim())) {\n      throw new FavoriteValidationError(\n        `Favorite metadata cannot contain inline image data URLs (${path})`,\n      )\n    }\n    return\n  }\n\n  if (!value || typeof value !== 'object') {\n    return\n  }\n\n  if (seen.has(value as object)) {\n    return\n  }\n  seen.add(value as object)\n\n  if (Array.isArray(value)) {\n    value.forEach((item, index) => {\n      assertFavoriteMetadataHasNoInlineImages(item, `${path}[${index}]`, seen)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/favorite/storage-guards.ts#L62-L98","documentation":"Storage guard (assertFavoriteMetadataHasNoInlineImages) that rejects favorite metadata containing inline image data URLs. It recursively walks the metadata value with cycle tracking (WeakSet) and throws FavoriteValidationError naming the offending path when any string matches INLINE_IMAGE_DATA_URL_RE.","triggerScenarios":"Saving or normalizing a favorite whose metadata contains a string matching an inline image data URL (data:image/...;base64,...) at any nesting depth — e.g. metadata.thumbnail or a deeply nested preview field.","commonSituations":"Attaching generated-image previews or avatars as base64 strings in metadata instead of URLs/asset IDs; metadata copied from APIs that inline base64 images.","solutions":["Replace inline data URLs in metadata with external URLs or asset IDs","Strip fields matching /^data:image\\// before saving","Store large binaries in dedicated blob storage and keep only references in favorite metadata"],"exampleFix":"// before\nfavorite.metadata = { preview: `data:image/png;base64,${b64}` };\n\n// after\nfavorite.metadata = { previewUrl: await uploadAndGetUrl(b64) };","handlingStrategy":"validation","validationCode":"const INLINE_IMAGE_RE = /^data:image\\/[a-z+.-]+;base64,/i;\nconst metadataHasInlineImage = (m: unknown): boolean => {\n  if (typeof m === 'string') return INLINE_IMAGE_RE.test(m.trim());\n  if (m && typeof m === 'object') return Object.values(m).some(metadataHasInlineImage);\n  return false;\n};\nif (metadataHasInlineImage(favorite.metadata)) delete favorite.metadata.preview;","typeGuard":"const isSafeMetadata = (m: unknown): boolean => !metadataHasInlineImage(m);","tryCatchPattern":"try {\n  await manager.addFavorite(fav);\n} catch (e) {\n  if (e instanceof FavoriteValidationError && /inline image/.test(e.message)) {\n    // message names the offending path; remove that field and retry\n  }\n}","preventionTips":["Never store base64 images in favorite metadata; use URLs or asset IDs","Recursively scan metadata for data:image URLs before saving","Upload generated previews to blob storage and keep only references"],"tags":["validation","metadata","base64","storage-limits"],"backgroundTag":"inline-base64-rejected","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}