{"record":{"id":"b739564fe819c2bf","repo":"multica-ai/multica","slug":"unsupported-file-format-q-must-be-png-jpg-j","errorCode":null,"errorMessage":"unsupported file format %q: must be .png, .jpg, .jpeg, .gif, or .webp","messagePattern":"unsupported file format %q: must be \\.png, \\.jpg, \\.jpeg, \\.gif, or \\.webp","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_agent.go","lineNumber":925,"sourceCode":"\t\treturn err\n\t}\n\n\tfilePath, _ := cmd.Flags().GetString(\"file\")\n\tif filePath == \"\" {\n\t\treturn fmt.Errorf(\"--file is required\")\n\t}\n\n\t// Validate file exists.\n\tinfo, err := os.Stat(filePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"file not found: %w\", err)\n\t}\n\n\t// Validate extension.\n\text := strings.ToLower(filepath.Ext(filePath))\n\tvalidExts := map[string]bool{\".png\": true, \".jpg\": true, \".jpeg\": true, \".gif\": true, \".webp\": true}\n\tif !validExts[ext] {\n\t\treturn fmt.Errorf(\"unsupported file format %q: must be .png, .jpg, .jpeg, .gif, or .webp\", ext)\n\t}\n\n\t// Client-side size guard: reject files > 5MB.\n\tconst maxSize = 5 << 20 // 5 MB\n\tif info.Size() > maxSize {\n\t\treturn fmt.Errorf(\"file too large: %d bytes (max 5MB)\", info.Size())\n\t}\n\n\tfileData, err := os.ReadFile(filePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read file: %w\", err)\n\t}\n\n\t// Defensive re-check: guard against TOCTOU race where the file\n\t// was swapped between stat and read.\n\tif len(fileData) > maxSize {\n\t\treturn fmt.Errorf(\"file too large: %d bytes (max 5MB)\", len(fileData))\n\t}","sourceCodeStart":907,"sourceCodeEnd":943,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_agent.go#L907-L943","documentation":"Returned by `multica agent avatar` when the lowercased extension of the file is not in {.png, .jpg, .jpeg, .gif, .webp}. The check is purely extension-based on the path — the actual bytes are not sniffed — so renaming a BMP to .png passes here and will be caught (or accepted) server-side later.","triggerScenarios":"`--file avatar.bmp`, `--file avatar.svg`, `--file avatar.heic`, a file with no extension, or a double-suffixed name like `avatar.png.txt`.","commonSituations":"iPhone HEIC exports, SVG logos, screenshots saved as .tiff/.bmp, or designers handing off unsupported formats.","solutions":["Convert the image to an allowed format: `magick input.heic output.png` (or `convert`/`sips`/an online converter)","Rename genuinely valid files whose extension is wrong: `mv avatar.avatar.png avatar.png`","Pick PNG for logos/screenshots and JPEG for photos to also keep size under the 5MB cap"],"exampleFix":"# before\nmultica agent avatar agt_1 --file logo.svg\n# Error: unsupported file format \".svg\": must be .png, .jpg, .jpeg, .gif, or .webp\n\n# after\nmagick logo.svg logo.png\nmultica agent avatar agt_1 --file logo.png","handlingStrategy":"validation","validationCode":"case \"$AVATAR_FILE\" in\n  *.png|*.jpg|*.jpeg|*.gif|*.webp) : ;;\n  *) echo \"unsupported format; convert to png/jpg/jpeg/gif/webp\"; exit 1 ;;\nesac","typeGuard":"var validAvatarExt = map[string]bool{\".png\": true, \".jpg\": true, \".jpeg\": true, \".gif\": true, \".webp\": true}\n\nfunc hasValidAvatarExt(path string) bool {\n\treturn validAvatarExt[strings.ToLower(filepath.Ext(path))]\n}","tryCatchPattern":"ext := strings.ToLower(filepath.Ext(filePath))\nif !validExts[ext] {\n\treturn fmt.Errorf(\"unsupported file format %q: must be .png, .jpg, .jpeg, .gif, or .webp\", ext)\n}","preventionTips":["Convert HEIC/SVG/BMP sources to PNG or JPEG before upload","Keep the extension honest — do not rename foreign formats","Prefer PNG for logos, JPEG for photos"],"tags":["cli","filesystem","validation","image","avatar"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}