{"record":{"id":"f05c861528756bbf","repo":"mastra-ai/mastra","slug":"metadata-avatarurl-contains-invalid-base64","errorCode":null,"errorMessage":"metadata.avatarUrl contains invalid base64","messagePattern":"metadata\\.avatarUrl contains invalid base64","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/validate-avatar.ts","lineNumber":34,"sourceCode":"\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) {\n    throw new HTTPException(400, { message: 'metadata.avatarUrl is empty' });\n  }\n\n  if (byteLength > AVATAR_MAX_BYTES) {\n    throw new HTTPException(413, {\n      message: `metadata.avatarUrl exceeds ${AVATAR_MAX_BYTES}-byte limit (got ${byteLength})`,\n    });\n  }\n}\n","sourceCodeStart":16,"sourceCodeEnd":48,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/validate-avatar.ts#L16-L48","documentation":"HTTP 400 from validateMetadataAvatarUrl: the base64 payload inside the data URL must be strict base64 — non-zero length, multiple of 4 characters, valid charset, and correct padding. Buffer.from is lenient, so the server validates explicitly and rejects sloppy encodings.","triggerScenarios":"Truncated base64 strings, strings with whitespace/newlines or URL-safe characters (-, _), payloads with wrong '=' padding, or empty payloads after the mime segment.","commonSituations":"Copy-paste from logs introducing line breaks; using base64url encoding from JWT-style tooling; truncating very large payloads; hand-concatenating data URLs.","solutions":["Re-encode the image bytes with standard base64 (Buffer.from(bytes).toString('base64')) and no whitespace.","Strip newlines/whitespace and fix '=' padding to make length a multiple of 4.","Replace URL-safe base64 (-, _) with standard characters (+, /)."],"exampleFix":"// before\nconst avatarUrl = 'data:image/png;base64,' + btoa(bytes).replace(/\\+/g, '-').replace(/\\//g, '_');\n// after\nconst avatarUrl = 'data:image/png;base64,' + Buffer.from(bytes).toString('base64');","handlingStrategy":"validation","validationCode":"const B64_RE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\nconst payload = metadata.avatarUrl?.split(',')[1] ?? '';\nif (!payload.length || payload.length % 4 !== 0 || !B64_RE.test(payload)) {\n  throw new Error('avatarUrl base64 payload is invalid');\n}","typeGuard":"function isStrictBase64(s: string): boolean {\n  return s.length > 0 && s.length % 4 === 0 && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(s);\n}","tryCatchPattern":"try {\n  await saveAgent({ metadata });\n} catch (e) {\n  if (e instanceof HTTPException && e.status === 400 && e.message.includes('invalid base64')) {\n    metadata.avatarUrl = reEncodeStandardBase64(metadata.rawAvatarBytes);\n    await saveAgent({ metadata });\n  } else throw e;\n}","preventionTips":["Use standard base64 (not base64url) when building data URLs.","Strip whitespace/newlines from base64 strings before embedding.","Re-encode from raw bytes rather than copying base64 out of logs."],"tags":["http-400","base64","encoding","validation"],"backgroundTag":"invalid-base64","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}