Summary
While publishing an App with multiple bundled Executas to the Anna staging environment using anna-app apps publish, I encountered two related issues:
- The platform appears to maintain an Executa version that increments with each
publishattempt. This does not appear to be the same version sequence as the version declared in the localmanifest.json. Once these two sequences diverge, a normally incremented local version can collide with a version that the platform has already created or frozen. - Rerunning the command after a failed publish appears to create additional upload sessions. After only a few retries, the
10/hourupload rate limit is reached, preventing further investigation or recovery.
This is more than a display issue. My current hypothesis is that each apps publish attempt may increment a platform-side version, while the manifest version of an individual bundled Executa does not change unless the developer updates it locally. The platform version can therefore move ahead of the local manifest version. When the local version is later incremented to a number that the platform has already occupied or frozen, the upload may fail with BINARY_VERSION_IMMUTABLE. Repeated attempts to resolve that failure can then trigger UPLOAD_RATE_LIMITED.
Environment
- Anna environment:
https://staging.anna.partners - Anna App CLI:
v0.1.34 - Publish command:
anna-app apps publish - Local platform: macOS
- App slug:
anna-presenton - The App contains three bundled Executas:
ppt-engineppt-generanna-search
- Example Tool ID used in this report:
tool-lightvoss-anna-search-7ym3jyqv
The project defines versions as follows:
- The App version is declared by the
versionfield inppt-app/app.json. - Each Executa’s publish version is declared in its
executa.jsonand kept in sync with theversionin the correspondingmanifest.json. - The App references these Executas through
bundled:<handle>identifiers, such asbundled:anna-search.
When the issue first occurred, the locally declared version and binary artifact version for anna-search were both 0.1.1. I later had to bump the local version several times while investigating, so the current repository version may differ from the version used in this reproduction.
Issue 1: The platform-assigned version and local manifest version form two conflicting version sequences
Using anna-search as an example, its initial local manifest version and binary build version were both 0.1.1. After several App publish attempts, however, the platform UI showed a sequence of incrementing version records. The attached screenshot shows all of the following at the same time:
- The version list on the left contains
v0.1.2,v0.1.3, andv0.1.4. - With
v0.1.2selected, the Executa metadata on the right showsversion: v0.1.2. - In the Distribution section of the same record, the package name and storage URLs still contain
v0.1.1.
In other words, the same Executa record exposes at least two version values: the platform record version is v0.1.2, while the local manifest and binary package version is v0.1.1.
Based on how these versions changed across repeated publish attempts, I suspect that apps publish automatically increments a platform-side Executa version on every attempt, even when the bundled Executa’s local manifest version has not changed or when the overall App publish eventually fails. If so:
- The platform version continues to increase with each publish attempt.
- The local Executa version increases only when the developer updates
manifest.jsonandexecuta.json. - The platform version can move ahead of the local version and occupy version numbers that the local project may use later.
- When the local version is later bumped to a number that the platform has already occupied or frozen, an immutable-version conflict can occur even though this is the first time the local project has published that version’s content.
I cannot yet confirm whether the platform version is generated by the server, rewritten by the App publishing flow, or derived from another field. However, the platform UI and binary URLs indicate that two inconsistent version values are being retained and used at the same time.
Actual result
Later in the investigation, I bumped both the local anna-search manifest.json and executa.json versions to 0.1.4. The anna-search@0.1.4 value in the CLI output correctly matched the local declaration at that point. However, the platform already had a frozen 0.1.4 version for the same Executa, so the upload failed with the following error:
publishing bundled executa "ppt-engine" (executas/ppt-engine)…
✓ bundled:ppt-engine → tool-lightvoss-ppt-engine-kqhra9hy (v4.0.6)
publishing bundled executa "ppt-gener" (executas/ppt-gener)…
✓ bundled:ppt-gener → tool-lightvoss-ppt-gener-2r765c57 (v3.1.3)
publishing bundled executa "anna-search" (executas/anna-search)…
✗ binary upload failed (409 BINARY_VERSION_IMMUTABLE): tool-lightvoss-anna-search-7ym3jyqv@0.1.4 (darwin-arm64) is already frozen into a published app with different content — bump the executa version and re-upload
✗ failed to publish bundled executa "anna-search" (executas/anna-search)
The problem here is not that the CLI incorrectly read 0.1.4 during this publish attempt. 0.1.4 was the local manifest version at the time. The underlying issue is that, before the local version was raised to 0.1.4, the platform’s incrementing version appears to have already reached and occupied 0.1.4. As a result, a normal local version bump still collided with an immutable version that already existed on the platform.
This raises the following questions:
- Does the platform-side version shown in the UI increment on every
apps publishattempt, regardless of whether the local manifest version changed? - If the overall App publish fails, does the platform still create and freeze a new Executa version?
- How are the platform-assigned version and local manifest version used for records, uploads, and immutability checks? Why do they share the same version-number namespace?
- If the local manifest version is lower than the platform’s incrementing version, how should a developer select the next version that will not conflict?
Expected result
- The platform should clearly distinguish between the platform-assigned version and the local manifest version. If they represent the same Executa release version, there should be one authoritative source instead of two independent sequences.
- If versions must be assigned by the server, the documentation and CLI output should explain the mapping clearly, and server-assigned versions should not occupy the namespace used by local manifest versions.
- If the version is intended to come from
executa.json/manifest.json, the platform version list, metadata, and immutability checks should use that version consistently and should not silently increment it based on publish attempts. - A failed App publish should not create or freeze an Executa version that was never successfully published. At minimum, it should not prevent a developer from later using the same version number for the first valid publish of that local version.
- For conflicts with an already frozen version, the CLI should ideally perform a preflight check before creating an upload session or uploading a binary. The error should show the local declared version, the server-resolved version, and the existing version being compared.
Issue 2: Failed retries quickly exhaust the upload-session limit
After encountering the immutable-version conflict, I updated the configuration or version and reran anna-app apps publish. Because the App contains three bundled Executas, each invocation starts again with the first Executa. After several failed attempts, the following error appeared:
publishing bundled executa "ppt-engine" (executas/ppt-engine)…
✗ binary upload failed (429 UPLOAD_RATE_LIMITED): too many upload sessions — limit 10/hour
✗ failed to publish bundled executa "ppt-engine" (executas/ppt-engine)
The CLI reports only a 10/hour limit. It does not explain:
- What exactly counts as one upload session: one command invocation, one Executa, one target platform, or one binary artifact?
- Whether a session still counts against the limit when the upload fails during a version check or another step.
- Whether repeated uploads with the same content can reuse an existing result based on the content hash instead of creating another session.
- Whether the limit is scoped to the user, PAT, App, Tool ID, or environment.
- How much quota remains and exactly when it resets.
An App publish may process several Executas sequentially. If a later Executa fails, the next retry processes the earlier Executas again. This makes a 10/hour limit very easy to exhaust during investigation. Even when a developer is only trying to resolve one publish failure, a small number of retries can block further work for an hour.
Expected result
- Errors that can be detected before upload, such as version conflicts or manifest validation failures, should not create or consume binary upload sessions.
- When an Executa with the same content hash has already uploaded successfully, retrying the App publish should reuse that result.
- If an App publish fails partway through, it should be possible to resume from the failed Executa instead of re-uploading earlier Executas whose content has not changed.
- A
429response should include and display the quota scope, current usage, reset time, orRetry-Aftervalue. - If
apps pushfollowed byapps cutis the only recommended flow and avoids these issues, the documentation should clearly explain how it differs fromapps publishin version assignment, freeze timing, retry idempotency, and upload quotas. As long asapps publishremains available, it should either remain reliably usable or provide actionable migration guidance.
Steps to reproduce
- Prepare an App containing multiple bundled Executas, each configured with local binary artifacts.
- Declare the same version in an Executa’s
executa.jsonandmanifest.json, then build binary artifacts containing that version number. - Keep one Executa’s local manifest version unchanged and run
anna-app apps publishseveral times. A later bundled Executa can be made to fail so that the full App publish flow must be retried. - After each attempt, inspect the Executa version list in the platform UI. Check whether the platform version continues to increment while the local manifest version remains unchanged, and whether failed App publishes also create new versions.
- Compare the version metadata, Distribution URL, local manifest version, and binary filename for the same platform record.
- Bump the local manifest version to a version number that the platform has already reached or occupied, rebuild the binary, and publish again.
- Check whether the platform returns
BINARY_VERSION_IMMUTABLE, stating that the local version is already frozen with different content. - Continue adjusting or bumping the version and retrying. After several publish attempts, check whether
UPLOAD_RATE_LIMITED: limit 10/houris returned.
Impact
- The platform-assigned version and local manifest version exist in parallel, so developers cannot reliably determine which Executa version to use for the next publish.
- Repeatedly bumping versions to work around platform-side conflicts creates many meaningless immutable version records.
- Retrying a failed publish is not idempotent and repeatedly uploads Executas whose content has not changed.
- The upload-session limit provides no usage or recovery information. Once the limit is reached, investigation must stop, significantly increasing the feedback cycle.
- Inconsistent versions across the platform version list, metadata, and actual binary package make rollback, auditing, and debugging more difficult.
Questions for the platform team
- For bundled Executas, which field determines the final published version in the
apps publish,apps push, andapps cutflows? Does the server increment a version on every publish attempt, including attempts that ultimately fail? - In the screenshot, the platform record and metadata show
v0.1.2, while the Distribution package name and URL showv0.1.1. Is this expected behavior? - Can the
BINARY_VERSION_IMMUTABLEpreflight check happen before upload and return a detailed comparison of the local and server-side versions? - How is the
10/hourupload-session limit counted? Do failed or duplicate uploads count, what is the quota scope, and when does it reset? - Can publishing an App with multiple Executas support content-hash deduplication, reuse of successful steps, and resumable retries?
I can provide the complete CLI logs, the corresponding versions of app.json, executa.json, and manifest.json, binary filenames and SHA-256 hashes, and the platform screenshot if more information is needed for investigation.
