0.89.0

playcanvas/engine0.89.0Sep 25, 2026by takahirom

Upgrading?

AI Summary

The packaged desktop app now bundles necessary Java modules to prevent failures on Linux and macOS, and API error logging is improved to show provider-specific details for rate limits.

Key Highlights

  • Bundles trimmed Java runtime modules to fix `BackendNotSupportedException` and `NoClassDefFoundError`
  • 429 API errors now display the provider's error body (e.g., insufficient quota) instead of a generic message
  • Package size increased by ~2 MB due to additional runtime modules

New Features

  • Enhanced error logging for API rate limits and quota issues

Full Release Notes

The packaged desktop app no longer fails on missing Java modules, and a 429 from the AI provider now says why it was returned.

## The Packaged App Bundles the Java Modules It Uses (#456)

The dmg/msi/deb ship a trimmed Java runtime that only had the modules Compose Desktop includes by default. On Linux, saving an API key failed with `BackendNotSupportedException: No available keyring backend found`, because the keyring backend needs `jdk.security.auth`. Playing a scenario failed with `NoClassDefFoundError: java/sql/Timestamp` from Maestro's JS engine, which needs `java.sql`; this was reproduced on the macOS app, and the Linux and Windows packages use the same trimmed runtime.

The runtime now includes the modules `./gradlew arbigent-ui:suggestRuntimeModules` reports for the app's dependencies. The dmg grows by about 2 MB (from 235.5 MB to 237.6 MB on macOS), and the installed app by about 7 MB. `arbigent` CLI runs on your own JDK and is unaffected.

Thank you, @rlanyi, for the report in #449, which already narrowed both failures down to the missing modules with `--limit-modules`.

## A 429 Shows the Provider's Error Body (#457)

OpenAI returns HTTP 429 both for a temporary rate limit and for `insufficient_quota`, and Gemini, Azure OpenAI and other OpenAI-compatible endpoints send their own 429 bodies. Every 429 used to be logged as a plain `Rate limit exceeded`. The provider's body is now in the message, for OpenAI-compatible endpoints and Anthropic alike:

```
I: Rate limit exceeded: {"error":{"message":"You exceeded your current quota, please check your plan and billing details. ...","type":"insufficient_quota","code":"insufficient_quota"}}. Waiting for 10 seconds.
```

The retry behavior does not change: a 429 is still waited out and retried, so you can now see from the log whether waiting will help.

Error bodies for 429 and other API errors reach logs, step feedback and reports, so they are redacted first. The configured API key is removed as before, and API-key-like tokens that a provider echoes back (`sk-...`, `AIza...`, such as the partially masked key in OpenAI's 401 message) are replaced with `****` in full. The body is capped at 1,000 characters.

Thank you, @rlanyi, for reporting in #450 that `insufficient_quota` was hidden behind the rate limit message.

## What's Changed
* Bundle the runtime modules the packaged UI needs by @takahirom in https://github.com/takahirom/arbigent/pull/456
* Show the provider's 429 error body and mask API keys in API errors by @takahirom in https://github.com/takahirom/arbigent/pull/457


**Full Changelog**: https://github.com/takahirom/arbigent/compare/0.88.0...0.89.0

Related Repositories