{"record":{"id":"0919ca8caefebfdf","repo":"multica-ai/multica","slug":"upload-avatar-w","errorCode":null,"errorMessage":"upload avatar: %w","messagePattern":"upload avatar: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_agent.go","lineNumber":956,"sourceCode":"\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}\n\n\tctx, cancel := context.WithTimeout(context.Background(), cli.AtLeastAPITimeout(60*time.Second))\n\tdefer cancel()\n\n\t// Agent existence pre-check.\n\tvar agent map[string]any\n\tif err := client.GetJSON(ctx, \"/api/agents/\"+args[0], &agent); err != nil {\n\t\treturn fmt.Errorf(\"get agent: %w\", err)\n\t}\n\n\tid, url, err := client.UploadFileWithURL(ctx, fileData, filePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"upload avatar: %w\", err)\n\t}\n\n\tbody := map[string]any{\"avatar_url\": url}\n\tvar result map[string]any\n\tif err := client.PutJSON(ctx, \"/api/agents/\"+args[0], body, &result); err != nil {\n\t\treturn fmt.Errorf(\"update agent avatar: %w\", err)\n\t}\n\n\toutput, _ := cmd.Flags().GetString(\"output\")\n\tif output == \"json\" {\n\t\treturn cli.PrintJSON(os.Stdout, map[string]any{\n\t\t\t\"id\":         id,\n\t\t\t\"agent_id\":   args[0],\n\t\t\t\"avatar_url\": url,\n\t\t})\n\t}\n\n\theaders := []string{\"ID\", \"AGENT_ID\", \"AVATAR_URL\"}","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_agent.go#L938-L974","documentation":"Wrapped error returned when the avatar bytes cannot be uploaded via client.UploadFileWithURL — the multipart/binary upload step of `multica agent avatar`, executed after the agent existence pre-check passes. Causes include network failure mid-upload, exceeding the 60s context timeout (cli.AtLeastAPITimeout), auth rejection on the upload endpoint, or a server-side content rejection (corrupt image data despite a valid extension).","triggerScenarios":"Slow or dropped connection during a ~5MB upload, server-side upload endpoint misconfigured (storage backend down), token lacking upload scope, or a renamed non-image file whose bytes fail server sniffing.","commonSituations":"Uploading over VPN/weak Wi-Fi, object storage (S3-compatible) credentials expired on the server, renamed .bmp to .png, large GIF approaching the timeout.","solutions":["Retry on a stable connection; check the server logs for the underlying upload error","Verify the file is genuinely the format its extension claims (`file avatar.png`), re-export if it is a renamed foreign format","If uploads consistently time out, use a smaller image (resize/re-encode) to finish well under 60s","Confirm the server's storage backend is healthy (its logs will show S3/local-storage errors)"],"exampleFix":"# before\nmultica agent avatar agt_1 --file renamed.bmp.png   # actually BMP bytes\n# Error: upload avatar: 400: invalid image data\n\n# after\nmagick renamed.bmp.png avatar.png\nmultica agent avatar agt_1 --file avatar.png","handlingStrategy":"retry","validationCode":"file \"$AVATAR_FILE\"   # confirm bytes match the extension\nsize=$(stat -c %s \"$AVATAR_FILE\"); [ \"$size\" -le 5242880 ] || exit 1","typeGuard":null,"tryCatchPattern":"id, url, err := client.UploadFileWithURL(ctx, fileData, filePath)\nif err != nil {\n\treturn fmt.Errorf(\"upload avatar: %w\", err) // transient network: safe to retry whole command\n}","preventionTips":["Verify the file's real format with `file` before uploading","Keep uploads small so they finish well under the 60s timeout","Retry once on transient network errors; investigate if it persists"],"tags":["cli","upload","network","avatar"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}