diff --git a/nix/agent-modules/forge.nix b/nix/agent-modules/forge.nix index 19dc9649..775f794d 100644 --- a/nix/agent-modules/forge.nix +++ b/nix/agent-modules/forge.nix @@ -246,16 +246,22 @@ in exit 0 fi TOKEN=$(cat "$TOKEN_FILE") - IMAGE=$(base64 -w 0 < ${iconPng}) + # The base64'd icon can exceed Linux's MAX_ARG_STRLEN (128 KiB + # per exec argument), so it must never be passed on a command + # line — not to jq as --arg, not to curl as -d. Route it through + # files instead. + IMAGE_FILE=$(mktemp) + PAYLOAD_FILE=$(mktemp) + trap 'rm -f "$IMAGE_FILE" "$PAYLOAD_FILE"' EXIT + base64 -w 0 < ${iconPng} > "$IMAGE_FILE" # Forgejo POST /user/avatar expects {"image":""} — just the # raw base64 string, NOT a data URI (data:image/png;base64,...). - # Use jq to build the payload so the large base64 value is safely quoted. - PAYLOAD=$(jq -n --arg img "$IMAGE" '{image:$img}') + jq -n --rawfile img "$IMAGE_FILE" '{image:($img|rtrimstr("\n"))}' > "$PAYLOAD_FILE" RESP=$(curl -sf --max-time 10 \ -X POST "$FORGE_URL/api/v1/user/avatar" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ - -d "$PAYLOAD" \ + --data-binary @"$PAYLOAD_FILE" \ -w "\n%{http_code}" 2>/dev/null || true) CODE=$(printf '%s' "$RESP" | tail -1) if [ "$CODE" = "204" ] || [ "$CODE" = "200" ]; then