expo / expo/eas-cli

EAS_GRADLE_CACHE: cleanup never removes entries, so saves permanently fail once the archive exceeds ~2 GiB

Open
#3,937 0 comments 4 reactions 0 assignees View on GitHub
needs review
Dominant language
TypeScript
Stars
1.4k
Forks
236
Avg merge
3d 1h
Merged PRs (30d)
91

Description

### Build/Submit details page URL

https://expo.dev/accounts/asula/projects/dawn-xyz/builds/10d1908e-424c-45ce-a460-ab7d8b97435d

### Summary

With `EAS_GRADLE_CACHE=1`, the build cache enters a permanent failure loop on active projects:

1. The cleanup configured by your init script does nothing — its own log proves it: `[EAS] Gradle build cache entries before cleanup: 5199` → `after build: 5337 (was 5199)`, growth on every build, never a removal (retention likely can't fire because extraction resets entry timestamps).
2. Once the archive crosses ~2 GiB, the storage PUT in `uploadCacheAsync` is rejected — `Error: Unexpected response from cache server (400): Bad Request` — on every build:

```
Gradle cache archive size: 2.2 GB
Uploading cache...
Failed to save Gradle cache
```

3. The exact key is therefore never written, so every restore is a prefix match of the same stale oversized archive — the loop never self-heals, even across lockfile changes.
4. All of this is silent: builds succeed and the 400 is only visible in the structured log's `err` field.

Likely related: the ccache prune before save (`ccache --evict-older-than s`) evicts objects written *during* the build — a 30-min build with ~17k ccache writes saved a 10.8 MB archive, and the next build restored a cache with 16 files / 0.0 GiB. So neither cache layer persists, and all C++ recompiles every build.

Suggested: validate size at session creation (or raise the cap), log the PUT response body, surface save failures in the UI, and make retention work on ephemeral workers.

### Managed or bare?

Managed (CNG/prebuild)

### Environment

Server-side EAS Build issue — image `ubuntu-26.04-jdk-17-ndk-r27b`, resource class `medium`, SDK 56 / RN 0.85, pnpm, ~13 CMake native modules. Local env not relevant.

### Error output

_No response_

### Reproducible demo or steps to reproduce from a blank project

Time/scale-dependent, not reproducible from a blank project — but observable on any project: enable `EAS_GRADLE_CACHE=1`, run two builds, and watch the init-script entry counts only increase regardless of the 3-day retention. Once accumulated past ~2 GiB (weeks, for a project with many native modules and several profiles sharing the lockfile-hash key), every save 400s. Example builds from 2026-07-02: `10d1908e-424c-45ce-a460-ab7d8b97435d` (production), `0a01138e-6bea-4141-8dc9-3dc74e6c8880` (staging). Full logs available on request.

Main cuts: the impact section, the restore/error log blocks (kept one-line quotes inline), four of the six suggested fixes, the env-info dump (replaced with the one line that matters — it's a server-side bug), and the ccache detail compressed to one paragraph. If they push back on the missing expo-env-info output, it takes 10 seconds to paste in from my previous message.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.