IMPORTANT: Developer documentation for the current development branch. This content is unreleased, may change without notice, and must not be treated as Buildish release documentation.
Troubleshooting
Cache miss on every build
Symptom: The job summary shows “Base cache: miss” or “Base cache: partial hit” every run, even on the same branch with no dependency changes.
Diagnostic steps:
-
Check the family and lineage shown in the job summary. The prepare step prints the current ref lineage and exact restored generation, when any. Search for the lineage prefix in the GitHub Actions cache list (
Settings → Actions → Caches). If no generation exists, check whether a writable finalize completed successfully on the previous run. -
Check for a changed partition fingerprint. The fingerprint segment of the cache key is the SHA-256 of your partition configuration. Any change to
cache-partitions— including adding, removing, or reordering a partition, or changing a glob — produces a new fingerprint and therefore a new key lineage. This is expected and correct; after the first successful build on the new configuration the cache will hit again. -
Check whether the Java major version changed. Switching between Java 17, 21, and 24 produces different cache families. Ensure
actions/setup-javauses the same major version on every run. -
Check the cache eviction policy. GitHub Actions caches are evicted after 7 days of inactivity and when the total storage cap for the repository is reached. An evicted entry looks identical to a new key from the action’s perspective.
-
Check the finalize save status.
not-requiredis expected after an unchanged cache hit and means no duplicate immutable generation was written.failed,not-saved, ormissing-pathsmeans the summary must not show a published generation; inspect the warning for the backend or path error. Aggregator publication failures fail the job because merged worker state is not yet durable.
GitHub Actions cache storage keeps filling up
Symptom: Repository cache storage approaches the GitHub Actions cache cap, cache saves stop being useful, or old cache entries are evicted before later jobs can reuse them.
Diagnostic steps:
-
Keep timestamp GC enabled.
cache-gc-mode: timestampis the default and prunes managed files before standalone or distributed-aggregator jobs save the base cache when modification and effective access times are both older thancache-gc-older-than-days. -
Tune the cutoff. The default cutoff is
14days. Lower values prune more aggressively, but the action rejects values below2days because common runner filesystems may not update access times on every read. -
Review custom partitions. Broad custom
cache-partitionscan include generated or low-value files that grow quickly. Disable or narrow partitions that do not materially improve build time. -
Expect Maven to redownload pruned artifacts. Maven local repositories are safe to prune conservatively because Maven can resolve old dependencies again when needed. If a workflow must run without network access, increase
cache-gc-older-than-daysor setcache-gc-mode: off.
Delta artifact not found by aggregator
Symptom: The aggregator’s prepare step fails with Dependent delta artifact discovery failed.
Diagnostic steps:
-
Check the effective read-only policy. A read-only aggregator intentionally performs no artifact lookup and reports
skipped-read-only; missing artifacts are not an error in that mode. If the workflow only aggregates writable events, use a trusted-eventifcondition to skip the aggregator job entirely. -
Verify the
dependent-jobsvalue on the aggregator matches the exact job key of each worker. The job key is the YAML key in thejobs:map, not thename:field. For example, if the worker is defined asjobs: { build-worker-a: … }, the aggregator must listdependent-jobs: build-worker-a. -
Check whether the worker’s finalize step actually ran. If the worker build failed and the step running the action was skipped or the post-action hook was suppressed, no delta artifact was uploaded. The aggregator must still run (
if: always()or equivalent) to clean up; it will report every missing or invalid configured worker rather than silently producing a broken cache. A successful writable worker uploads an explicit envelope even when it made no changes. -
Check for matrix job names with special characters. Matrix dimension values such as
ubuntu-latest / Java 21contain spaces and slashes that are sanitized when constructing the artifact name, but thedependent-jobsinput must use the original unsanitized job key (e.g.build (ubuntu-latest, 21)). Use thegithub-job-nameinput on both worker and aggregator to assign simple, stable names that are independent of matrix labeling:1# worker 2- uses: buildish-tooling/buildish-mammoth-cache/actions/github/gradle@<sha> 3 with: 4 job-mode: distributed-worker 5 github-job-name: worker-a 6# aggregator 7- uses: buildish-tooling/buildish-mammoth-cache/actions/github/gradle@<sha> 8 with: 9 job-mode: distributed-aggregator 10 dependent-jobs: worker-a, worker-b 11 github-job-name: aggregator -
Check rerun selection diagnostics. The aggregator selects the newest unambiguous worker attempt not newer than its own attempt, so aggregator-only and failed-job reruns can reuse retained earlier envelopes. Duplicate artifacts for the same worker attempt are rejected as ambiguous instead of being selected arbitrarily.
-
Check that the job is running on GitHub Actions with runtime artifact service variables. Same-run worker upload and aggregator discovery use GitHub-provided Actions runtime credentials, not
actions: write. If this is a nonstandard runner environment, inspect the first artifact client error rather than broadeningGITHUB_TOKENpermissions.
Gradle wrapper provisioning failure
Symptom: The action fails during provisioning with a message like
Checksum mismatch for gradle-wrapper.jar, GPG signature verification failed, or a network
error downloading from services.gradle.org.
Diagnostic steps:
-
Checksum mismatch or signature failure. This means the downloaded JAR does not match the expected digest published by Gradle. Possible causes:
- A network proxy altered the response in transit. Check whether your runner uses a corporate proxy and whether it terminates TLS.
- The
gradle-wrapper.propertiesfile specifies a customdistributionUrlor the wrapper JAR in the repository was modified. Verify the file against the official Gradle wrapper validation service athttps://services.gradle.org/versions/all. - The wrapper was hand-edited or generated by a tool other than
gradle wrapper. Re-generate it with./gradlew wrapper --gradle-version=<version>.
-
GPG key not in the allowlist. Gradle occasionally rotates its signing key. If the action rejects the signature with
key fingerprint … is not in the pinned allowlist, open an issue or pull request against thesrc/build-tool/gradle/wrapper/signature.tspinned key list. In the meantime, you can verify the new key independently againsthttps://gradle.com/security. -
Network timeout or rate limit. Wrapper downloads require outbound HTTPS to
services.gradle.organd (for authenticated lookups) toapi.github.com. If your runner is network-restricted, pre-install the Gradle wrapper JAR in the repository or use a proxy that allowlists those hosts. For GitHub API rate limits, pass agithub-tokenwith at least read-onlycontentsaccess. -
Windows: wrong
gpgbinary selected. On Windows runners multiplegpgvariants may be on the PATH. Set theBUILDISH_MAMMOTH_CACHE_GRADLE_GPG_COMMANDenvironment variable to the full path of the correct binary before the action runs.
Missing github-token
Symptom: The Gradle action logs a warning about unauthenticated API access, or wrapper provisioning intermittently fails with HTTP 403 or HTTP 429 responses.
Explanation: The github-token input (and the GITHUB_TOKEN environment variable fallback)
is used exclusively by the Gradle action to download wrapper JARs from GitHub Releases via
the GitHub API. It is not used by the Maven action and is not required when the wrapper JAR is
already present in the repository.
How to pass it:
1- uses: buildish-tooling/buildish-mammoth-cache/actions/github/gradle@<sha>
2 with:
3 github-token: ${{ secrets.GITHUB_TOKEN }}
The token is applied only to requests targeting api.github.com and raw.githubusercontent.com.
It is never written to workflow summaries, log output, or post-action persisted state.