langgenius/dify · error · AppUnavailableError

app_unavailable

app_unavailable

Error message

App unavailable, please check your app configurations.

What it means

Raised as AppUnavailableError (error_code app_unavailable, HTTP 400) at the top of ChatAudioApi.post in explore/audio.py (POST /installed-apps/<installed_app_id>/audio-to-text). When installed_app.app_with_session returns None the underlying App is gone, so there is nothing to run speech-to-text against. AppUnavailableError's fixed description is 'App unavailable, please check your app configurations.'

Source

Thrown at api/controllers/console/explore/audio.py:56

from .. import console_ns

logger = logging.getLogger(__name__)

register_schema_model(console_ns, TextToAudioPayload)
register_response_schema_models(console_ns, AudioBinaryResponse, AudioTranscriptResponse)


@console_ns.route(
    "/installed-apps/<uuid:installed_app_id>/audio-to-text",
    endpoint="installed_app_audio",
)
class ChatAudioApi(InstalledAppResource):
    @console_ns.response(200, "Success", console_ns.models[AudioTranscriptResponse.__name__])
    def post(self, installed_app: InstalledApp):
        app_model = installed_app.app_with_session(session=db.session())
        if app_model is None:
            raise AppUnavailableError()

        file = request.files["file"]

        try:
            response = AudioService.transcript_asr(
                app_model=app_model,
                file=file,
                session=db.session(),
                end_user=None,
            )

            return response
        except services.errors.app_model_config.AppModelConfigBrokenError:
            logger.exception("App model config broken.")
            raise AppUnavailableError()
        except NoAudioUploadedServiceError:
            raise NoAudioUploadedError()
        except AudioTooLargeServiceError as e:

View on GitHub (pinned to ef8544b173)

Solutions

  1. Verify the installed_app_id still points to a live App (re-list installed apps).
  2. Reinstall the app from the explore marketplace if the source was removed.
  3. On the client, treat app_unavailable as 'app deleted, refresh'.
  4. Confirm the authenticated account can access the app's tenant.

Example fix

// before
POST /installed-apps/<installed-app-id>/audio-to-text   // app deleted -> 400 app_unavailable
// after
installed = await GET /installed-apps          // pick a live one
POST /installed-apps/<installed[0].id>/audio-to-text
Defensive patterns

Strategy: validation

Validate before calling

async function audioToText(installedAppId) {
  const installed = await fetch(`/installed-apps`).then(r => r.json());
  const entry = (installed.items ?? []).find(i => i.id === installedAppId && i.app);
  if (!entry) throw new Error('app_unavailable');
  return fetch(`/installed-apps/${installedAppId}/audio-to-text`, { method: 'POST', body: formData });
}

Type guard

function isLiveInstalledApp(entry) { return !!entry && !!entry.app; }

Try / catch

try { await audioToText(id); } catch (e) { if (e.code === 'app_unavailable') { refreshInstalledApps(); return; } throw e; }

Prevention

When it happens

Trigger: Calling the installed-app audio endpoint after the App referenced by the InstalledApp was deleted or could not be loaded. The `if app_model is None` guard fires immediately and raises.

Common situations: Installed app whose source app was removed; app soft-deleted but installed-app record remains; tenant/app scope mismatch on the session; exploring a stale installed-app link.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/0d8b44dd1ddc0d6f. Report an issue: GitHub.