{"record":{"id":"4c62b162961acea5","repo":"mastra-ai/mastra","slug":"metadata-avatarurl-must-be-a-valid-data-url-data","errorCode":null,"errorMessage":"metadata.avatarUrl must be a valid data URL (data:<mime>;base64,<data>)","messagePattern":"metadata\\.avatarUrl must be a valid data URL \\(data:<mime>;base64,<data>\\)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/validate-avatar.ts","lineNumber":20,"sourceCode":"\nconst AVATAR_MAX_BYTES = 512 * 1024; // 512 KB\n\n/**\n * Validates `metadata.avatarUrl` if present.\n * Ensures it's a well-formed data URL and the decoded payload is ≤ 512 KB.\n * No-ops when metadata is absent or doesn't contain avatarUrl.\n */\nexport function validateMetadataAvatarUrl(metadata: Record<string, unknown> | undefined): void {\n  if (!metadata || !('avatarUrl' in metadata) || metadata.avatarUrl === null || metadata.avatarUrl === undefined)\n    return;\n  if (typeof metadata.avatarUrl !== 'string') {\n    throw new HTTPException(400, { message: 'metadata.avatarUrl must be a string' });\n  }\n\n  const dataUrl = metadata.avatarUrl;\n  const match = dataUrl.match(/^data:([^;]+);base64,(.+)$/);\n  if (!match) {\n    throw new HTTPException(400, {\n      message: 'metadata.avatarUrl must be a valid data URL (data:<mime>;base64,<data>)',\n    });\n  }\n\n  // `Buffer.from(..., 'base64')` decodes leniently — it silently ignores\n  // invalid characters and never throws. Validate the payload format strictly\n  // before measuring its byte length so malformed input is rejected.\n  const base64Payload = match[2]!;\n  const isStrictBase64 =\n    base64Payload.length > 0 &&\n    base64Payload.length % 4 === 0 &&\n    /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(base64Payload);\n  if (!isStrictBase64) {\n    throw new HTTPException(400, { message: 'metadata.avatarUrl contains invalid base64' });\n  }\n  const byteLength = Buffer.from(base64Payload, 'base64').byteLength;\n\n  if (byteLength === 0) {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/validate-avatar.ts#L2-L38","documentation":"HTTP 400 from validateMetadataAvatarUrl: an avatarUrl string must match the strict data-URL format data:<mime>;base64,<data>. Plain http(s) URLs, bare base64 strings, or malformed data URLs are rejected.","triggerScenarios":"Passing metadata.avatarUrl as 'https://example.com/avatar.png', 'iVBORw0KGgo...' (no data: prefix), or 'data:image/png,urlencoded' (not base64).","commonSituations":"Sending remote image URLs expecting the server to fetch them; stripping the data: prefix when processing images client-side; legacy agents storing external URLs in avatarUrl.","solutions":["Convert the image to a base64 data URL client-side (read file, base64-encode, prefix with data:<mime>;base64,).","Store external URLs under a different metadata key if remote URLs are intended.","Validate the format with a regex before submitting."],"exampleFix":"// before\nmetadata: { avatarUrl: 'https://example.com/avatar.png' }\n// after\nmetadata: { avatarUrl: `data:image/png;base64,${fs.readFileSync('avatar.png').toString('base64')}` }","handlingStrategy":"validation","validationCode":"const DATA_URL_RE = /^data:([^;]+);base64,(.+)$/;\nif (typeof metadata?.avatarUrl === 'string' && !DATA_URL_RE.test(metadata.avatarUrl)) {\n  throw new Error('avatarUrl must be a base64 data URL');\n}","typeGuard":"function isBase64DataUrl(v: unknown): v is string {\n  return typeof v === 'string' && /^data:[^;]+;base64,.+$/.test(v);\n}","tryCatchPattern":"try {\n  await saveAgent({ metadata });\n} catch (e) {\n  if (e instanceof HTTPException && e.status === 400 && e.message.includes('valid data URL')) {\n    metadata.avatarUrl = await fileToDataUrl(metadata.rawAvatar);\n    await saveAgent({ metadata });\n  } else throw e;\n}","preventionTips":["Always convert images to data URLs at the input boundary (file picker handler).","Never store external http(s) URLs in avatarUrl.","Add the data-URL regex to shared client-side form validation."],"tags":["http-400","format-validation","metadata","data-url"],"backgroundTag":"invalid-data-url","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}