{"record":{"id":"e2ce2c515294036d","repo":"sipeed/picoclaw","slug":"invalid-base64-image-data","errorCode":null,"errorMessage":"invalid base64 image data","messagePattern":"invalid base64 image data","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/channels/pico/pico.go","lineNumber":1410,"sourceCode":"\n\theader, data, found := strings.Cut(mediaURL, \",\")\n\tif !found || strings.TrimSpace(data) == \"\" {\n\t\treturn fmt.Errorf(\"image data URL is malformed\")\n\t}\n\tif !strings.Contains(header, \";base64\") {\n\t\treturn fmt.Errorf(\"image data URL must be base64 encoded\")\n\t}\n\tmimeType, _, _ := strings.Cut(strings.TrimPrefix(header, \"data:\"), \";\")\n\tif _, ok := allowedInlineImageMIMETypes[mimeType]; !ok {\n\t\treturn fmt.Errorf(\"unsupported image format: %s\", mimeType)\n\t}\n\n\tdata = strings.TrimSpace(data)\n\tif base64.StdEncoding.DecodedLen(len(data)) > config.DefaultMaxMediaSize {\n\t\treturn fmt.Errorf(\"image exceeds %d byte limit\", config.DefaultMaxMediaSize)\n\t}\n\tif _, err := base64.StdEncoding.DecodeString(data); err != nil {\n\t\treturn fmt.Errorf(\"invalid base64 image data\")\n\t}\n\n\treturn nil\n}\n\n// setContextUsagePayload adds context window usage stats to a pico payload.\nfunc setContextUsagePayload(payload map[string]any, u *bus.ContextUsage) {\n\tif u == nil {\n\t\treturn\n\t}\n\tpayload[\"context_usage\"] = map[string]any{\n\t\t\"used_tokens\":         u.UsedTokens,\n\t\t\"total_tokens\":        u.TotalTokens,\n\t\t\"history_tokens\":      u.HistoryTokens,\n\t\t\"compress_at_tokens\":  u.CompressAtTokens,\n\t\t\"summarize_at_tokens\": u.SummarizeAtTokens,\n\t\t\"used_percent\":        u.UsedPercent,\n\t}","sourceCodeStart":1392,"sourceCodeEnd":1428,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/pico/pico.go#L1392-L1428","documentation":"Thrown by validateInlineImageDataURL when base64.StdEncoding.DecodeString rejects the trimmed body of the data URL. StdEncoding strictly requires the standard alphabet (A-Z, a-z, 0-9, +, /), correct = padding, and no whitespace inside the body (only leading/trailing spaces are trimmed by the preceding strings.TrimSpace). Any deviation — URL-safe alphabet, missing padding, embedded newlines, truncation — fails here.","triggerScenarios":"Producing the data URL with base64.RawURLEncoding / base64.URLEncoding (uses - and _ instead of + and /), omitting padding with base64.RawStdEncoding, embedding line-wrapped base64 (MIME-style \\n every 76 chars), or truncating the payload so the final quantum is incomplete.","commonSituations":"Code that base64-encodes for JWT/URL contexts (URL-safe) reused for image inlining; copying base64 from PEM or MIME files that contain newlines; a string being trimmed or re-wrapped in transit (JSON, YAML, clipboard) breaking padding; hand-assembling the data URL and dropping trailing '=' characters.","solutions":["Encode with base64.StdEncoding.EncodeToString (padded, standard alphabet) when building data URLs.","Strip internal whitespace/newlines before validation: data = strings.NewReplacer(\"\\n\", \"\", \"\\r\", \"\", \" \", \"\").Replace(data).","If you receive URL-safe base64, transcode it: decode with base64.URLEncoding (or RawURLEncoding) and re-encode with base64.StdEncoding.","Verify the data URL body length is a multiple of 4 after cleanup (padded standard base64)."],"exampleFix":"// before: URL-safe, unpadded — rejected by StdEncoding\ndataURL := \"data:image/png;base64,\" + base64.RawURLEncoding.EncodeToString(img)\n\n// after: standard alphabet with padding, no embedded whitespace\nimport \"strings\"\nclean := strings.NewReplacer(\"\\n\", \"\", \"\\r\", \"\", \" \", \"\").Replace(rawBody)\ndataURL := \"data:image/png;base64,\" + clean // body produced by base64.StdEncoding.EncodeToString","handlingStrategy":"validation","validationCode":"func isValidStdBase64Body(dataURL string) bool {\n    _, body, ok := strings.Cut(dataURL, \",\")\n    if !ok { return false }\n    body = strings.TrimSpace(body)\n    body = strings.NewReplacer(\"\\n\", \"\", \"\\r\", \"\", \" \", \"\").Replace(body)\n    _, err := base64.StdEncoding.DecodeString(body)\n    return err == nil\n}","typeGuard":null,"tryCatchPattern":"// if err != nil && strings.Contains(err.Error(), \"invalid base64\") -> re-encode the source bytes with base64.StdEncoding and retry once; otherwise surface to sender","preventionTips":["Always produce data URL bodies with base64.StdEncoding.EncodeToString","Transcode URL-safe base64 (- and _) to the standard alphabet before inlining","Strip newlines from base64 copied out of PEM/MIME files"],"tags":["pico","base64","encoding","image","validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}