Description
After deploying a Code App with npx power-apps push, static binary assets (JPG, PNG) included in the Vite build output (dist/) are served corrupted by the storageproxy. The files return HTTP 200 with the correct Content-Type header, but the response body is larger than the original file and unrenderable. Text-based assets (JS, CSS, HTML, SVG) are unaffected.
Steps to Reproduce
- Create a Code App with
@microsoft/power-apps-vite
- Place an image in
src/assets/ (e.g., a 196KB JPG) and import it in a component:
import heroImg from '../assets/Splash.jpg';
// ...
<img src={heroImg} alt="Hero" />
- Build with
npm run build — Vite emits the image to dist/assets/Splash-<hash>.jpg
- Deploy with
npx power-apps push
- Open the deployed app and inspect the image request in DevTools (Network tab)
Expected Behavior
The image file should be served with its original byte content and render correctly in the browser.
Actual Behavior
- The image returns HTTP 200 OK with
Content-Type: image/jpeg (correct)
- The
Content-Length is larger than the original file
- The image does not render (broken image icon in
<img>, empty space in CSS background-image)
- Opening the image URL directly in a new browser tab also shows a broken image
Evidence
| File |
Original size |
Served Content-Length |
Ratio |
Renders? |
| Splash.jpg (196KB JPG) |
195,725 bytes |
351,508 bytes |
1.80x |
No |
| test-pixel.png (minimal 1x1 PNG) |
70 bytes |
92 bytes |
1.31x |
No |
| index.js (JS bundle) |
198,310 bytes |
(correct) |
1.00x |
Yes |
| index.css (CSS) |
4,870 bytes |
(correct) |
1.00x |
Yes |
| vite.svg (SVG) |
1,497 bytes |
(correct) |
1.00x |
Yes |
The inflation ratio varies by file, which is consistent with binary content being re-encoded as UTF-8 text (bytes >127 become multi-byte sequences, with the inflation depending on the byte distribution of each file).
Workaround
Force Vite to inline all images as base64 data URLs by setting assetsInlineLimit in vite.config.ts:
export default defineConfig({
plugins: [react(), powerApps()],
build: {
assetsInlineLimit: 300000, // Inline images as base64 to bypass storageproxy corruption
},
});
This embeds the image directly in the JS bundle, avoiding the storageproxy serving path entirely. This works but increases bundle size (~1.33x per image) and does not scale for apps with many or large images.
Environment
- PAC CLI: 2.5.1+gab954cf
- @microsoft/power-apps: ^1.0.17
- @microsoft/power-apps-vite: ^1.0.2
- @microsoft/power-apps-cli: ^0.10.0
- Vite: ^7.2.4
- React: ^19.2.0
- OS: Windows 11 Enterprise
- Browser: Chrome/Edge (latest)
- Power Platform region: prod (Canada)
Related Issues
These issues involve binary corruption in the connector execution layer (JSON.stringify on binary data). The issue reported here may share a similar root cause (text encoding applied to binary content) but occurs in the static asset serving path (storageproxy), not the connector layer.
Description
After deploying a Code App with
npx power-apps push, static binary assets (JPG, PNG) included in the Vite build output (dist/) are served corrupted by the storageproxy. The files return HTTP 200 with the correctContent-Typeheader, but the response body is larger than the original file and unrenderable. Text-based assets (JS, CSS, HTML, SVG) are unaffected.Steps to Reproduce
@microsoft/power-apps-vitesrc/assets/(e.g., a 196KB JPG) and import it in a component:npm run build— Vite emits the image todist/assets/Splash-<hash>.jpgnpx power-apps pushExpected Behavior
The image file should be served with its original byte content and render correctly in the browser.
Actual Behavior
Content-Type: image/jpeg(correct)Content-Lengthis larger than the original file<img>, empty space in CSSbackground-image)Evidence
Content-LengthThe inflation ratio varies by file, which is consistent with binary content being re-encoded as UTF-8 text (bytes >127 become multi-byte sequences, with the inflation depending on the byte distribution of each file).
Workaround
Force Vite to inline all images as base64 data URLs by setting
assetsInlineLimitinvite.config.ts:This embeds the image directly in the JS bundle, avoiding the storageproxy serving path entirely. This works but increases bundle size (~1.33x per image) and does not scale for apps with many or large images.
Environment
Related Issues
format: "binary"body parameters upload corrupted files. #230 — Connector operations withformat: "binary"body parameters upload corrupted files (similar binary corruption, different code path)These issues involve binary corruption in the connector execution layer (
JSON.stringifyon binary data). The issue reported here may share a similar root cause (text encoding applied to binary content) but occurs in the static asset serving path (storageproxy), not the connector layer.